48 | SELECT (COUNT(?gc) AS ?cnt)
49 | WHERE {
50 | ?gc :hasGrandparent ?gp .
51 | }
52 | '''
53 | for r in g.query(q):
54 | cnt = int(r[0])
55 | assert cnt == 7
56 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/toc-RDFClosure.Literals-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | Literals
7 |
8 |
9 |
10 |
11 |
13 | Module Literals
14 |
15 | Classes
16 | LiteralProxies
20 | Variables
21 | __author__ __license__ __package__
25 | [hide private ]
27 |
28 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/toc-RDFClosure.Closure-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | Closure
7 |
8 |
9 |
10 |
11 |
13 | Module Closure
14 |
15 | Classes
16 | Core Variables
18 | __author__ __license__ __package__ debugGlobal offlineGeneration
24 | [hide private ]
26 |
27 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/redirect.html:
--------------------------------------------------------------------------------
1 | Epydoc Redirect Page
2 |
3 |
4 |
5 |
6 |
7 |
8 |
18 |
19 | Epydoc Auto-redirect page
20 |
21 | When javascript is enabled, this page will redirect URLs of
22 | the form redirect.html#dotted.name to the
23 | documentation for the object with the given fully-qualified
24 | dotted name.
25 |
26 |
27 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/README.rst:
--------------------------------------------------------------------------------
1 | |Original Author DOI| |PyPI badge|
2 |
3 | |OWL-RL Logo|
4 |
5 | .. |Original Author DOI| image:: https://zenodo.org/badge/9385/RDFLib/OWL-RL.svg
6 | :target: http://dx.doi.org/10.5281/zenodo.14543
7 |
8 | .. |PyPI badge| image:: https://badge.fury.io/py/owlrl.svg
9 | :target: https://badge.fury.io/py/owlrl
10 |
11 | .. |OWL-RL Logo| image:: OWL-RL-250.png
12 | :target: http://owl-rl.readthedocs.io/
13 |
14 |
15 | OWL-RL
16 | ======
17 |
18 | A simple implementation of the OWL2 RL Profile, as well as a basic RDFS inference, on top of RDFLib. Based mechanical forward chaining. The distribution contains:
19 |
20 | **OWL-RL**: the Python library. You should copy the directory somewhere into your :code:`PYTHONPATH`. Alternatively, you can also run the :code:`python setup.py install` script in the directory.
21 |
22 | * :code:`scripts/RDFConvertService`: can be used as a CGI script to invoke the library. It may have to be adapted to the local server setup.
23 |
24 | * :code:`scripts/owlrl`: script that can be run locally on to transform a file into RDF (on the standard output). Run the script with :code:`-h` to get the available flags.
25 |
26 | The package requires Python version 3.5 or higher; it depends on `RDFLib`_; version 4.2.2 or higher is required. If you need the python 2.7.x compatible version, see the @/py2 branch in this repository.
27 |
28 | .. _RDFLib: https://github.com/RDFLib
29 |
30 | For the details on RDFS, see the `RDF Semantics Specification`_; for OWL 2 RL, see the `OWL 2 Profile specification`_.
31 |
32 | .. _RDF Semantics Specification: http://www.w3.org/TR/rdf11-mt/
33 | .. _OWL 2 Profile specification: http://www.w3.org/TR/owl2-profiles/#Reasoning_in_OWL_2_RL_and_RDF_Graphs_using_Rules
34 |
35 | View the **OWL-RL documentation** online: http://owl-rl.readthedocs.io/
36 |
37 | To view the changelog for this software library, see `CHANGELOG.rst `_.
38 |
39 | This software is released under the W3C© SOFTWARE NOTICE AND LICENSE. See `LICENSE.txt `_.
40 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/owlrl/RDFS.py:
--------------------------------------------------------------------------------
1 | """
2 | RDF(S) terms. Note that the set of terms is *complete*, i.e., it includes *all* OWL 2 terms, regardless of whether the
3 | term is used in OWL 2 RL or not.
4 |
5 | **Requires**: `RDFLib`_, 4.0.0 and higher.
6 |
7 | .. _RDFLib: https://github.com/RDFLib/rdflib
8 |
9 | **License**: This software is available for use under the `W3C Software License`_.
10 |
11 | .. _W3C Software License: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
12 |
13 | **Organization**: `World Wide Web Consortium`_
14 |
15 | .. _World Wide Web Consortium: http://www.w3.org
16 |
17 | **Author**: `Ivan Herman`_
18 |
19 | .. _Ivan Herman: http://www.w3.org/People/Ivan/
20 | """
21 |
22 | import rdflib
23 | from rdflib import Namespace
24 |
25 | RDFNS = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
26 | RDFSNS = Namespace("http://www.w3.org/2000/01/rdf-schema#")
27 |
28 | # RDF Classes
29 | Seq = RDFNS["Seq"]
30 | Bag = RDFNS["Bag"]
31 | Alt = RDFNS["Alt"]
32 | Statement = RDFNS["Statement"]
33 | Property = RDFNS["Property"]
34 | XMLLiteral = RDFNS["XMLLiteral"]
35 | HTMLLiteral = RDFNS["HTML"]
36 | LangString = RDFNS["LangString"]
37 | List = RDFNS["List"]
38 |
39 | # RDF Properties
40 | rdf_subject = RDFNS["subject"]
41 | rdf_predicate = RDFNS["predicate"]
42 | rdf_object = RDFNS["object"]
43 | rdf_type = RDFNS["type"]
44 | value = RDFNS["value"]
45 | first = RDFNS["first"]
46 | rest = RDFNS["rest"]
47 | # and _n where n is a non-negative integer
48 |
49 | # RDF Resources
50 | nil = RDFNS["nil"]
51 |
52 | Resource = RDFSNS["Resource"]
53 | Class = RDFSNS["Class"]
54 | subClassOf = RDFSNS["subClassOf"]
55 | subPropertyOf = RDFSNS["subPropertyOf"]
56 | comment = RDFSNS["comment"]
57 | label = RDFSNS["label"]
58 | rdfs_domain = RDFSNS["domain"]
59 | rdfs_range = RDFSNS["range"]
60 | seeAlso = RDFSNS["seeAlso"]
61 | isDefinedBy = RDFSNS["isDefinedBy"]
62 | Literal = RDFSNS["Literal"]
63 | Container = RDFSNS["Container"]
64 | ContainerMembershipProperty = RDFSNS["ContainerMembershipProperty"]
65 | member = RDFSNS["member"]
66 | Datatype = RDFSNS["Datatype"]
67 |
--------------------------------------------------------------------------------
/mimir/src/main/api/owl/ReasonTimeout.kt:
--------------------------------------------------------------------------------
1 | package api.owl
2 |
3 | import kotlinx.coroutines.runBlocking
4 | import kotlinx.coroutines.withTimeoutOrNull
5 | import org.springframework.http.MediaType
6 | import org.springframework.http.HttpHeaders
7 | import org.springframework.http.ResponseEntity
8 | import org.springframework.http.HttpHeaders.CONTENT_TYPE
9 | import org.springframework.http.HttpStatus
10 | import org.springframework.web.bind.annotation.PostMapping
11 | import org.springframework.web.bind.annotation.RequestBody
12 | import org.springframework.web.bind.annotation.RestController
13 | import api.ReasonerConfig
14 |
15 | data class ReasonTimeoutRequest(
16 | val data: String = "",
17 | val data_lang: String = "TTL",
18 | val profile: String = ReasonerConfig.DEFAULT_PROFILE,
19 | val timeout: Long = 60000
20 | )
21 |
22 | @RestController
23 | class ReasonTimeoutController {
24 |
25 | @PostMapping(
26 | "/api/owl/reason_timeout",
27 | consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE],
28 | produces = [MediaType.APPLICATION_JSON_UTF8_VALUE, MediaType.TEXT_PLAIN_VALUE])
29 | fun reasonTimeout(
30 | @RequestBody requestBody: ReasonTimeoutRequest
31 | ): ResponseEntity {
32 | val header = HttpHeaders()
33 |
34 | return runBlocking {
35 | // Runs ReasonResponse With a Timeout
36 | val response = withTimeoutOrNull(requestBody.timeout) {
37 | val request = ReasonRequest(requestBody.data, requestBody.data_lang, requestBody.profile)
38 | // delegate to ReasonResponse
39 | ReasonController().reason(request)
40 | }
41 |
42 | when(response) {
43 | null -> {
44 | // Time has run out, respond that
45 | header.add(CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
46 | return@runBlocking ResponseEntity("Time ran out for this request", header, HttpStatus.REQUEST_TIMEOUT)
47 | }
48 |
49 | else -> return@runBlocking response
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/mimir/src/main/api/model/Dot.kt:
--------------------------------------------------------------------------------
1 | package api.model
2 |
3 | import dot.DOTLang
4 | import loadModel
5 | import org.apache.jena.rdf.model.Model
6 | import org.apache.jena.riot.RDFDataMgr
7 | import org.apache.jena.riot.RDFFormat
8 | import org.apache.jena.riot.RDFLanguages
9 | import org.springframework.http.HttpHeaders
10 | import org.springframework.http.HttpStatus
11 | import org.springframework.http.MediaType
12 | import org.springframework.http.ResponseEntity
13 | import org.springframework.web.bind.annotation.PostMapping
14 | import org.springframework.web.bind.annotation.RequestBody
15 | import org.springframework.web.bind.annotation.RestController
16 | import java.io.ByteArrayOutputStream
17 |
18 |
19 | data class DotRequest(val data: String = "", val data_lang: String = "TTL")
20 |
21 | @RestController
22 | class DotController {
23 |
24 | @PostMapping(
25 | "/api/model/dot",
26 | consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE],
27 | produces = [MimeType.dot]
28 | )
29 | fun dot(@RequestBody requestBody: DotRequest): ResponseEntity {
30 |
31 | val header = HttpHeaders()
32 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.dot)
33 | if (requestBody.data.isBlank()) {
34 | return ResponseEntity("", header, HttpStatus.OK)
35 | }
36 | // Create a model on Memory
37 | val model: Model
38 |
39 | // Convert to DOT and save on ByteArray Stream
40 | val modelOnDOT = ByteArrayOutputStream()
41 |
42 | try {
43 | model = loadModel(requestBody.data, requestBody.data_lang)
44 | // Check if DOT lang is loaded
45 | val dotLang = DOTLang
46 | assert(RDFLanguages.isRegistered(dotLang)) {"Controller Error, DOT is not registered on Jena"}
47 | RDFLanguages.isRegistered(dotLang)
48 | // write to DOT
49 | RDFDataMgr.write(modelOnDOT, model, RDFFormat(DOTLang)) // Writes DOT to modelOnDOT
50 | } catch (e: Exception) {
51 | return ResponseEntity("", header, HttpStatus.INTERNAL_SERVER_ERROR)
52 | }
53 |
54 | return ResponseEntity(modelOnDOT.toString(), header, HttpStatus.OK)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/mimir/src/main/dot/DOTWriter.kt:
--------------------------------------------------------------------------------
1 | package dot
2 |
3 | import org.apache.jena.atlas.io.IndentedWriter
4 | import org.apache.jena.graph.Graph
5 | import org.apache.jena.riot.*
6 | import org.apache.jena.riot.adapters.RDFWriterRIOT
7 | import org.apache.jena.riot.system.PrefixMap
8 | import org.apache.jena.riot.system.RiotLib
9 | import org.apache.jena.riot.writer.WriterGraphRIOTBase
10 | import org.apache.jena.sparql.util.Context
11 | import java.io.OutputStream
12 | import java.io.Writer
13 |
14 |
15 | class DOTWriter: WriterGraphRIOTBase() {
16 | override fun getLang(): Lang {
17 | return RDFLanguages.contentTypeToLang("text/dot")
18 | }
19 |
20 | override fun write(out: Writer, graph: Graph, prefixMap: PrefixMap, baseURI: String, context: Context) {
21 | // MAYBE check charset tp be UTF-8
22 | val indentedWriter: IndentedWriter = RiotLib.create(out)
23 | output(indentedWriter, graph, prefixMap, baseURI, context)
24 | }
25 |
26 | override fun write(out: OutputStream, graph: Graph, prefixMap: PrefixMap, baseURI: String?, context: Context) {
27 | val indentedWriter = IndentedWriter(out)
28 | output(indentedWriter, graph, prefixMap, baseURI, context)
29 | }
30 |
31 | companion object DOTWriterFactory: WriterGraphRIOTFactory {
32 | override fun create(syntaxRDFFormat: RDFFormat?): WriterGraphRIOT {
33 | return DOTWriter()
34 | }
35 | }
36 |
37 | private fun output(
38 | indentedOutput: IndentedWriter,
39 | graph: Graph,
40 | prefixMap: PrefixMap,
41 | baseURI: String?,
42 | context: Context
43 | ) {
44 | val privateWriter = PrivateTurtleWriter(indentedOutput, prefixMap, baseURI, context)
45 | privateWriter.write(graph)
46 | indentedOutput.flush()
47 | }
48 |
49 | private class PrivateTurtleWriter(out: IndentedWriter, prefixMap: PrefixMap, baseURI: String?, context: Context) :
50 | DOTShell(out, prefixMap, baseURI, context) {
51 |
52 | internal fun write(graph: Graph) {
53 | writeGraphDOT(graph)
54 | }
55 | }
56 |
57 | // Model.write adapter - must be public.
58 | object RDFWriterDOT : RDFWriterRIOT("DOT")
59 | }
60 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/toc-RDFClosure.XsdDatatypes-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | XsdDatatypes
7 |
8 |
9 |
10 |
11 |
13 | Module XsdDatatypes
14 |
15 | Variables
16 | OWL_Datatype_Subsumptions OWL_RL_Datatypes RDFS_Datatype_Subsumptions RDFS_Datatypes
23 |
26 | __author__ __license__ __package__
30 | [hide private ]
32 |
33 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/OwlRLWrapper.kt:
--------------------------------------------------------------------------------
1 | package reasoner
2 |
3 | import api.ReasonerConfig
4 | import java.io.BufferedReader
5 | import java.nio.file.Files
6 | import java.nio.file.Paths
7 |
8 | class OwlRLWrapper (private val config: ReasonerConfig = ReasonerConfig) {
9 | var profile: String = config.DEFAULT_PROFILE
10 |
11 | init {
12 | try {
13 | // test getting the default file
14 | val defaultFilePath = Paths.get(config.DEFAULT_DATA_DIR+config.DEFAULT_DATA_NAME)
15 | Files.readAllBytes(defaultFilePath.toAbsolutePath())
16 | } catch (e: Exception) {
17 | println("ERROR: could not get test file path. \n Reason: ${e.message}")
18 | // throw error to be used at response time
19 | throw e
20 | }
21 | }
22 |
23 | fun infer(data: String, profile: String = this.profile): Pair {
24 | val type: String = when (profile.toLowerCase()) {
25 | config.RDFS_PROFILE -> config.RDFS_FLAG
26 | config.OWL_PROFILE -> config.OWL_FLAG
27 | else -> this.config.DEFAULT_FLAG // error, we'll use default one
28 | }
29 |
30 | // Create temp file with out model
31 | val tempDirectory = Paths.get(config.TMP_DIR_NAME).toFile()
32 | val tempFile = createTempFile(config.TMP_NAME_PREFIX, config.TMP_NAME_SUFFIX,tempDirectory)
33 | tempFile.writeText(data, Charsets.UTF_8)
34 |
35 | // Run OWL-RL
36 | val runtime: Runtime = Runtime.getRuntime()
37 | // Executes the command that runs the owlrl script (activates the environment first)
38 | val process = runtime.exec("${config.CMD_NAME}$type -f ${tempFile.path}")
39 |
40 | val inferenceResult: String = BufferedReader(process.inputStream.reader()).readText()
41 |
42 | // Read the error and skip the stacktrace
43 | var stack: Boolean = true
44 | var errorResult: String = ""
45 | process.errorStream.reader().readLines().forEach { line ->
46 | run {
47 | if (!stack) {
48 | errorResult += "$line\n"
49 | }
50 |
51 | // Skip StackTrace
52 | if (line.contains(" at line ") && stack) {
53 | stack = false
54 | }
55 | }
56 | }
57 |
58 | // Delete temp file to save space
59 | if (!tempFile.delete()) println("ERROR: could not delete ${tempFile.name}")
60 |
61 | return Pair(inferenceResult, errorResult)
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/mimir/src/main/api/model/BrowseUri.kt:
--------------------------------------------------------------------------------
1 | package api.model
2 |
3 |
4 | import dot.DOTLang
5 | import org.apache.jena.rdf.model.Model
6 | import org.apache.jena.rdf.model.ModelFactory
7 | import org.apache.jena.riot.RDFDataMgr
8 | import org.apache.jena.riot.RDFFormat
9 | import org.apache.jena.riot.RDFLanguages
10 | import org.springframework.http.HttpStatus
11 | import org.springframework.http.MediaType
12 | import org.springframework.http.ResponseEntity
13 | import org.springframework.web.bind.annotation.PostMapping
14 | import org.springframework.web.bind.annotation.RequestBody
15 | import org.springframework.web.bind.annotation.RestController
16 | import java.io.ByteArrayOutputStream
17 | import formatAs
18 |
19 |
20 | data class UriRequest(val url: String = "")
21 | data class UriResponse(val browse_error: String = "", val model_dot: String = "", val model_ttl: String = "")
22 |
23 | @RestController
24 | class BrowseUriController {
25 |
26 |
27 | @PostMapping(
28 | "/api/model/browse",
29 | consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE],
30 | produces = [MediaType.APPLICATION_JSON_UTF8_VALUE]
31 | )
32 | fun browseUri(@RequestBody requestBody: UriRequest): ResponseEntity{
33 | if (requestBody.url.isBlank()) {
34 | return ResponseEntity(UriResponse("Nothing to look up" + requestBody.url), HttpStatus.NO_CONTENT)
35 | }
36 |
37 | // Read Uri and load into Model
38 | val model : Model = ModelFactory.createDefaultModel()
39 | try {
40 | RDFDataMgr.read(model, requestBody.url)
41 |
42 | } catch (e: Exception) {
43 | return ResponseEntity(
44 | UriResponse("Apache Jena was unable to load data in a model. Error was: \n" +
45 | e.message.toString()),
46 | HttpStatus.OK,
47 | )
48 | }
49 |
50 | // Check if DOT lang is loaded
51 | val dotLang = DOTLang
52 | assert(RDFLanguages.isRegistered(dotLang)) {"Controller Error, DOT is not registered on Jena"}
53 | RDFLanguages.isRegistered(dotLang)
54 |
55 | val modelOnDot = ByteArrayOutputStream()
56 | try {
57 | RDFDataMgr.write(modelOnDot, model, RDFFormat(DOTLang))
58 | } catch (e:Exception) {
59 | return ResponseEntity(UriResponse(browse_error = e.message.toString()), HttpStatus.INTERNAL_SERVER_ERROR)
60 | }
61 |
62 | return ResponseEntity(UriResponse(model_dot = modelOnDot.toString(), model_ttl = model.formatAs("TTL").first), HttpStatus.OK)
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/LICENSES/OWL-RL's License:
--------------------------------------------------------------------------------
1 | License
2 | By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will
3 | comply with the following terms and conditions.
4 |
5 | Permission to copy, modify, and distribute this software and its documentation, with or without modification, for any
6 | purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the
7 | software and documentation or portions thereof, including modifications:
8 |
9 | - The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
10 | - Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the
11 | W3C Software Short Notice should be included (hypertext is preferred, text is permitted) within the body of any
12 | redistributed or derivative code.
13 | - Notice of any changes or modifications to the files, including the date changes were made. (We recommend you provide
14 | URIs to the location from which the code is derived.)
15 |
16 | Disclaimers
17 | THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES,
18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE
19 | OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR
20 | OTHER RIGHTS.
21 |
22 | COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY
23 | USE OF THE SOFTWARE OR DOCUMENTATION.
24 |
25 | The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software
26 | without specific, written prior permission. Title to copyright in this software and any associated documentation
27 | will at all times remain with copyright holders.
28 |
29 | Notes
30 | This version: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
31 |
32 | This formulation of W3C's notice and license became active on December 31 2002. This version removes the copyright
33 | ownership notice such that this license can be used with materials other than those owned by the W3C, reflects that
34 | ERCIM is now a host of the W3C, includes references to this specific dated version of the license, and removes the
35 | ambiguous grant of "use". Otherwise, this version is the same as the previous version and is written so as to preserve
36 | the Free Software Foundation's assessment of GPL compatibility and OSI's certification under the Open Source Definition.
37 |
--------------------------------------------------------------------------------
/mimir/src/main/api/tdb/GetModel.kt:
--------------------------------------------------------------------------------
1 | package api.tdb
2 |
3 | import org.apache.jena.query.Dataset
4 | import org.apache.jena.query.ReadWrite
5 | import org.apache.jena.rdf.model.Model
6 | import org.apache.jena.tdb.TDBFactory
7 | import org.springframework.http.HttpHeaders
8 | import org.springframework.http.HttpHeaders.CONTENT_TYPE
9 | import org.springframework.http.HttpStatus
10 | import org.springframework.http.ResponseEntity
11 | import org.springframework.web.bind.annotation.GetMapping
12 | import org.springframework.web.bind.annotation.RestController
13 | import api.TDBConfig
14 | import formatAs
15 | import toDOT
16 |
17 | data class GetModelResponse(
18 | val data: String = "",
19 | val dot: String = ""
20 | )
21 |
22 | @RestController
23 | class GetModelController {
24 |
25 | @GetMapping(
26 | "api/tdb/get_model"
27 | )
28 | fun getModel(): ResponseEntity {
29 | // Gets the contents of the TDB and returns it to the user
30 | val header = HttpHeaders()
31 |
32 | // get TDB directory
33 | val directory: String = TDBConfig.TDB_DIR
34 | val dataset: Dataset
35 |
36 | try {
37 | //access database
38 | dataset = TDBFactory.createDataset(directory)
39 | } catch (e: Exception) {
40 | // if we cannot access the database there is no point on continuing
41 | header.add(CONTENT_TYPE, MimeType.text)
42 | return ResponseEntity("Couldn't get TDB", header, HttpStatus.INTERNAL_SERVER_ERROR)
43 | }
44 |
45 | val modelString: String
46 | val dotModel: String
47 |
48 | dataset.begin(ReadWrite.READ)
49 | try {
50 | // get the model from the Database
51 | val model: Model = dataset.defaultModel
52 | // format as TTL
53 | modelString = model.formatAs("TTL").first
54 | // get DOT version
55 | dotModel = model.toDOT()
56 | } catch (e: Exception) {
57 | dataset.end()
58 | // there was an error on the model or converting it to DOT
59 | header.add(CONTENT_TYPE, MimeType.text)
60 | return ResponseEntity("Error processing Database: ${e.message}", header, HttpStatus.INTERNAL_SERVER_ERROR)
61 | } finally {
62 | // end connection
63 | dataset.end()
64 | }
65 |
66 | // send data to the user
67 | header.add(CONTENT_TYPE, MimeType.json)
68 | return ResponseEntity(
69 | GetModelResponse(data = modelString, dot = dotModel),
70 | header,
71 | HttpStatus.OK
72 | )
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/mimir/src/main/api/model/SyntaxCheckResponse.kt:
--------------------------------------------------------------------------------
1 | package api.model
2 |
3 | import org.springframework.web.bind.annotation.RestController
4 | import org.springframework.web.bind.annotation.PostMapping
5 | import org.springframework.web.bind.annotation.RequestBody
6 | import org.springframework.http.ResponseEntity
7 | import org.springframework.http.HttpStatus
8 | import org.springframework.http.MediaType
9 | import org.apache.jena.rdf.model.Model
10 | import org.apache.jena.riot.RDFDataMgr
11 | import org.apache.jena.riot.RDFFormat
12 | import org.apache.jena.riot.RDFLanguages
13 | import java.io.ByteArrayOutputStream
14 |
15 | import org.apache.jena.query.Query;
16 | import org.apache.jena.query.QueryFactory;
17 | import org.apache.commons.lang3.mutable.Mutable
18 | import com.google.common.hash.Hashing;
19 |
20 |
21 | import dot.DOTLang
22 | import loadModel
23 | import kotlin.collections.mutableListOf
24 | import kotlin.io.println
25 |
26 | data class SyntaxCheckRequest(val data: String = "", val data_lang: String = "TTL")
27 | data class SyntaxCheckResponse(val syntax_error: String = "", val data_dot: String = "")
28 |
29 | @RestController
30 | class SyntaxCheckController {
31 | var union_count = 0;
32 | @PostMapping(
33 | "/api/model/syntax_check",
34 | consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE],
35 | produces = [MediaType.APPLICATION_JSON_UTF8_VALUE]
36 | )
37 | fun syntaxCheck(@RequestBody requestBody: SyntaxCheckRequest): ResponseEntity {
38 | // base case
39 | if (requestBody.data.isBlank()) {
40 | return ResponseEntity(SyntaxCheckResponse("Nothing received"), HttpStatus.NO_CONTENT)
41 | }
42 |
43 | // Create a model on Memory
44 | val model: Model
45 | try {
46 | model = loadModel(requestBody.data, requestBody.data_lang)
47 | } catch (e: Exception) {
48 | return ResponseEntity(SyntaxCheckResponse(syntax_error = e.message.toString()), HttpStatus.OK)
49 | }
50 | // Check if DOT lang is loaded
51 | val dotLang = DOTLang
52 | assert(RDFLanguages.isRegistered(dotLang)) {"Controller Error, DOT is not registered on Jena"}
53 | RDFLanguages.isRegistered(dotLang)
54 |
55 | // Convert to DOT and save on ByteArray Stream
56 | val modelOnDOT = ByteArrayOutputStream()
57 | try {
58 | // write to DOT
59 | RDFDataMgr.write(modelOnDOT, model, RDFFormat(DOTLang)) // Writes DOT to modelOnDOT
60 |
61 | } catch (e: Exception) {
62 | return ResponseEntity(SyntaxCheckResponse(syntax_error = e.message.toString()), HttpStatus.INTERNAL_SERVER_ERROR)
63 | }
64 | return ResponseEntity(SyntaxCheckResponse(data_dot = modelOnDOT.toString() ), HttpStatus.OK)
65 | }
66 |
67 |
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### JetBrains template
3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
5 |
6 | # User-specific stuff
7 | .idea/**/workspace.xml
8 | .idea/**/tasks.xml
9 | .idea/**/usage.statistics.xml
10 | .idea/**/dictionaries
11 | .idea/**/shelf
12 |
13 | # Generated files
14 | .idea/**/contentModel.xml
15 |
16 | # Sensitive or high-churn files
17 | .idea/**/dataSources/
18 | .idea/**/dataSources.ids
19 | .idea/**/dataSources.local.xml
20 | .idea/**/sqlDataSources.xml
21 | .idea/**/dynamic.xml
22 | .idea/**/uiDesigner.xml
23 | .idea/**/dbnavigator.xml
24 |
25 | # Gradle
26 | .idea/**/gradle.xml
27 | .idea/**/libraries
28 |
29 | # Gradle and Maven with auto-import
30 | # When using Gradle or Maven with auto-import, you should exclude module files,
31 | # since they will be recreated, and may cause churn. Uncomment if using
32 | # auto-import.
33 | # .idea/modules.xml
34 | # .idea/*.iml
35 | # .idea/modules
36 | # *.iml
37 | # *.ipr
38 |
39 | # CMake
40 | cmake-build-*/
41 |
42 | # Mongo Explorer plugin
43 | .idea/**/mongoSettings.xml
44 |
45 | # File-based project format
46 | *.iws
47 |
48 | # IntelliJ
49 | out/
50 |
51 | # mpeltonen/sbt-idea plugin
52 | .idea_modules/
53 |
54 | # JIRA plugin
55 | atlassian-ide-plugin.xml
56 |
57 | # Cursive Clojure plugin
58 | .idea/replstate.xml
59 |
60 | # Crashlytics plugin (for Android Studio and IntelliJ)
61 | com_crashlytics_export_strings.xml
62 | crashlytics.properties
63 | crashlytics-build.properties
64 | fabric.properties
65 |
66 | # Editor-based Rest Client
67 | .idea/httpRequests
68 |
69 | # Android studio 3.1+ serialized cache file
70 | .idea/caches/build_file_checksums.ser
71 |
72 | ### Maven template
73 | # Project exclude paths
74 | /target/
75 | target/
76 | pom.xml.tag
77 | pom.xml.releaseBackup
78 | pom.xml.versionsBackup
79 | pom.xml.next
80 | release.properties
81 | dependency-reduced-pom.xml
82 | buildNumber.properties
83 | .mvn/timing.properties
84 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar
85 | .mvn/wrapper/maven-wrapper.jar
86 |
87 | ### Kotlin template
88 | # Compiled class file
89 | *.class
90 |
91 | # Log file
92 | *.log
93 |
94 | # BlueJ files
95 | *.ctxt
96 |
97 | # Mobile Tools for Java (J2ME)
98 | .mtj.tmp/
99 |
100 | # Package Files #
101 | *.jar
102 | *.war
103 | *.nar
104 | *.ear
105 | *.zip
106 | *.tar.gz
107 | *.rar
108 |
109 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
110 | hs_err_pid*
111 |
112 | # temp files
113 | mimir/src/main/reasoner/temp/*.ttl
114 | mimir/src/main/shex/temp/*
115 | mimir/src/main/resources/tdb/*
116 | /.idea/
117 | /mimir/linkeddata.iml
118 |
--------------------------------------------------------------------------------
/mimir/src/test/api/shape/ShexResponseControllerTest.kt:
--------------------------------------------------------------------------------
1 | package api.shape
2 |
3 | import org.junit.jupiter.api.Test
4 | import kotlin.test.assertEquals
5 |
6 | internal class ShexResponseControllerTest {
7 |
8 | @Test
9 | fun shexIsValid() {
10 | val data: String = """
11 | @prefix : .
12 | @prefix schema: .
13 | @prefix xsd: .
14 | @prefix foaf: .
15 |
16 |
17 | :dave schema:name "Dave"; # Fails as a :User
18 | schema:gender "XYY"; #
19 | schema:birthDate 1980 . # 1980 is not an xsd:date *)
20 |
21 | :emily schema:name "Emilee" ; # Passes
22 | schema:gender schema:Female . #
23 |
24 | :frank foaf:name "Frank" ; # Fails as a :User
25 | schema:gender: schema:Male . # missing schema:name *)
26 |
27 | :grace schema:name "Grace" ; # Fails as a :User
28 | schema:gender schema:Male ; #
29 | schema:knows _:x . # \_:x is not an IRI *)
30 |
31 | :harold schema:name "Harold" ; # Fails as a :User
32 | schema:gender schema:Male ;
33 | schema:knows :grace . # :grace does not conform to :User *)
34 | """.trimIndent()
35 | val lang = "TTL"
36 | val shex: String = """
37 | PREFIX :
38 | PREFIX schema:
39 | PREFIX xsd:
40 |
41 | :User {
42 | schema:name xsd:string ;
43 | schema:birthDate xsd:date? ;
44 | schema:gender [ schema:Male schema:Female ] OR xsd:string ;
45 | schema:knows IRI @:User*
46 | }
47 | """.trimIndent()
48 | val shapeMap: String = """
49 | @,
50 | @,
51 | @,
52 | :emily@:User,
53 | @:User,
54 | :emily@,
55 | :dave@:User
56 | """.trimIndent()
57 | val expectedReport = """
58 | ShEx Validation Report:
59 | ❌ does not conform with
60 | ❌ does not conform with
61 | ❌ does not conform with
62 | ✅ :emily conforms with :User
63 | ✅ conforms with :User
64 | ✅ :emily conforms with
65 | ❌ :dave does not conform with :User
66 | """.trimIndent()
67 |
68 | val testedClass = ShexIsValidController()
69 |
70 | val response = testedClass
71 | .shexIsValid(
72 | ShExRequest(data, lang, shex, shapeMap)
73 | )
74 |
75 | assertEquals(expectedReport, response.body!!.trim())
76 | }
77 | }
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/toc-RDFClosure-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | RDFClosure
7 |
8 |
9 |
10 |
11 |
13 | Module RDFClosure
14 |
15 | Classes
16 | DeductiveClosure Functions
18 |
21 | convert_graph interpret_owl_imports return_closure_class Variables
25 | AUTO FULL JSON NONE OWL RDF RDFA RDFS RDFXML TURTLE __author__ __license__ __package__ json_ld_available
40 | [hide private ]
42 |
43 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/PKG-INFO:
--------------------------------------------------------------------------------
1 | Metadata-Version: 1.2
2 | Name: owlrl
3 | Version: 5.2.1
4 | Summary: OWL-RL and RDFS based RDF Closure inferencing
5 | Home-page: https://github.com/RDFLib/OWL-RL/
6 | Author: Ivan Herman
7 | Author-email: ivan@ivan-herman.net
8 | Maintainer: Nicholas Car
9 | Maintainer-email: nicholas.car@csiro.au
10 | License: LICENSE.txt
11 | Download-URL: https://github.com/RDFLib/OWL-RL/archive/v5.2.1.tar.gz
12 | Description: |Original Author DOI|
13 |
14 | .. |Original Author DOI| image:: https://zenodo.org/badge/9385/RDFLib/OWL-RL.svg
15 | :target: http://dx.doi.org/10.5281/zenodo.14543
16 |
17 |
18 | OWL-RL
19 | ======
20 |
21 | A simple implementation of the OWL2 RL Profile, as well as a basic RDFS inference, on top of RDFLib. Based mechanical forward chaining. The distribution contains:
22 |
23 | **OWL-RL**: the Python library. You should copy the directory somewhere into your :code:`PYTHONPATH`. Alternatively, you can also run the :code:`python setup.py install` script in the directory.
24 |
25 | * :code:`scripts/RDFConvertService`: can be used as a CGI script to invoke the library. It may have to be adapted to the local server setup.
26 |
27 | * :code:`scripts/owlrl`: script that can be run locally on to transform a file into RDF (on the standard output). Run the script with :code:`-h` to get the available flags.
28 |
29 | The package requires Python version 3.5 or higher; it depends on `RDFLib`_; version 4.2.2 or higher is required. If you need the python 2.7.x compatible version, see the @/py2 branch in this repository.
30 |
31 | .. _RDFLib: https://github.com/RDFLib
32 |
33 | For the details on RDFS, see the `RDF Semanics Specification`_; for OWL 2 RL, see the `OWL 2 Profile specification`_.
34 |
35 | .. _RDF Semanics Specification: http://www.w3.org/TR/rdf11-mt/
36 | .. _OWL 2 Profile specification: http://www.w3.org/TR/owl2-profiles/#Reasoning_in_OWL_2_RL_and_RDF_Graphs_using_Rules
37 |
38 | View the **OWL-RL documentation** online: http://owl-rl.readthedocs.io/
39 | Keywords: Linked Data,Semantic Web,Python,triples,inferencing,RDF,OWL,OWL-RL,owlrl,RDFS
40 | Platform: UNKNOWN
41 | Classifier: Development Status :: 5 - Production/Stable
42 | Classifier: Topic :: Utilities
43 | Classifier: Topic :: Software Development :: Libraries :: Python Modules
44 | Classifier: Intended Audience :: Developers
45 | Classifier: License :: OSI Approved :: W3C License
46 | Classifier: Natural Language :: English
47 | Classifier: Programming Language :: Python
48 | Classifier: Programming Language :: Python :: 3
49 | Classifier: Programming Language :: Python :: 3.5
50 | Classifier: Programming Language :: Python :: 3.6
51 | Classifier: Programming Language :: Python :: 3.7
52 | Classifier: Programming Language :: Python :: 3.8
53 | Classifier: Programming Language :: Python :: 3 :: Only
54 | Classifier: Programming Language :: Python :: Implementation :: CPython
55 | Classifier: Programming Language :: Python :: Implementation :: PyPy
56 | Classifier: Operating System :: OS Independent
57 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: latin-1 -*-
3 | import re
4 | import os
5 | import io
6 | from setuptools import setup
7 |
8 | def open_local(paths, mode='r', encoding='utf8'):
9 | path = os.path.join(
10 | os.path.abspath(os.path.dirname(__file__)),
11 | *paths
12 | )
13 | return io.open(path, mode, encoding=encoding)
14 |
15 |
16 | with open_local(['owlrl', '__init__.py'], encoding='utf-8') as fp:
17 | try:
18 | version = re.findall(r"^__version__ = '([^']+)'\r?$",
19 | fp.read(), re.M)[0]
20 | except IndexError:
21 | raise RuntimeError('Unable to determine version.')
22 |
23 | with open_local(['README.rst']) as readme:
24 | long_description = readme.read()
25 |
26 | with open_local(['requirements.txt']) as req:
27 | found_requirements = req.read().split("\n")
28 | dependency_links = []
29 | requirements = []
30 | for f in found_requirements:
31 | if 'git+' in f:
32 | pkg = f.split('#')[-1]
33 | dependency_links.append(f.strip() + '-9876543210')
34 | requirements.append(pkg.replace('egg=', '').rstrip())
35 | else:
36 | requirements.append(f.strip())
37 |
38 | setup(
39 | name='owlrl',
40 | packages=['owlrl'],
41 | scripts=['scripts/owlrl', 'scripts/RDFConvertService'],
42 | package_dir={'owlrl': './owlrl'},
43 | version=version,
44 | description='OWL-RL and RDFS based RDF Closure inferencing for Python',
45 | author='Ivan Herman',
46 | author_email='ivan@ivan-herman.net',
47 | maintainer='Nicholas Car',
48 | maintainer_email='nicholas.car@csiro.au',
49 | url='https://github.com/RDFLib/OWL-RL/',
50 | download_url='https://github.com/RDFLib/OWL-RL/'\
51 | 'archive/v{:s}.tar.gz'.format(version),
52 | license='LICENSE.txt',
53 | keywords=['Linked Data', 'Semantic Web', 'Python', 'triples',
54 | 'inferencing', 'RDF', 'OWL', 'OWL-RL', 'owlrl', 'RDFS'],
55 | long_description=long_description,
56 | long_description_content_type='text/x-rst',
57 | classifiers=[
58 | 'Development Status :: 5 - Production/Stable',
59 | 'Topic :: Utilities',
60 | 'Topic :: Software Development :: Libraries :: Python Modules',
61 | 'Intended Audience :: Developers',
62 | 'License :: OSI Approved :: W3C License',
63 | 'Natural Language :: English',
64 | 'Programming Language :: Python',
65 | 'Programming Language :: Python :: 3',
66 | 'Programming Language :: Python :: 3.5',
67 | 'Programming Language :: Python :: 3.6',
68 | 'Programming Language :: Python :: 3.7',
69 | 'Programming Language :: Python :: 3.8',
70 | 'Programming Language :: Python :: 3 :: Only',
71 | 'Programming Language :: Python :: Implementation :: CPython',
72 | 'Programming Language :: Python :: Implementation :: PyPy',
73 | 'Operating System :: OS Independent'
74 | ],
75 | install_requires=requirements,
76 | tests_require=['pytest']+requirements,
77 | dependency_links=dependency_links
78 | )
79 |
80 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/docs/source/DatatypeHandling.rst:
--------------------------------------------------------------------------------
1 | DatatypeHandling
2 | ================
3 |
4 | .. automodule:: owlrl.DatatypeHandling
5 | :members:
6 | :undoc-members:
7 | :inherited-members:
8 | :show-inheritance:
9 |
10 |
11 | AltXSDToPYTHON Table
12 | --------------------
13 |
14 | .. note:: The code below is not extracted automatically from the source code.
15 |
16 | If there are any errors, please make a pull request or an issue: https://github.com/RDFLib/OWL-RL
17 |
18 | .. code-block:: python
19 |
20 | AltXSDToPYTHON = {
21 | ns_xsd["language"]: lambda v: _strToVal_Regexp(v, _re_language),
22 | ns_xsd["NMTOKEN"]: lambda v: _strToVal_Regexp(v, _re_NMTOKEN, re.U),
23 | ns_xsd["Name"]: lambda v: _strToVal_Regexp(v, _re_NMTOKEN, re.U, _re_Name_ex),
24 | ns_xsd["NCName"]: lambda v: _strToVal_Regexp(v, _re_NCName, re.U, _re_NCName_ex),
25 | ns_xsd["token"]: _strToToken,
26 | ns_rdf["PlainLiteral"]: _strToPlainLiteral,
27 | ns_xsd["boolean"]: _strToBool,
28 | ns_xsd["decimal"]: _strToDecimal,
29 | ns_xsd["anyURI"]: _strToAnyURI,
30 | ns_xsd["base64Binary"]: _strToBase64Binary,
31 | ns_xsd["double"]: _strToDouble,
32 | ns_xsd["float"]: _strToFloat,
33 | ns_xsd["byte"]: lambda v: _strToBoundNumeral(v, _limits_byte, int),
34 | ns_xsd["int"]: lambda v: _strToBoundNumeral(v, _limits_int, int),
35 | ns_xsd["long"]: lambda v: _strToBoundNumeral(v, _limits_long, int),
36 | ns_xsd["positiveInteger"]: lambda v: _strToBoundNumeral(v, _limits_positiveInteger, int),
37 | ns_xsd["nonPositiveInteger"]: lambda v: _strToBoundNumeral(v, _limits_nonPositiveInteger, int),
38 | ns_xsd["negativeInteger"]: lambda v: _strToBoundNumeral(v, _limits_negativeInteger, int),
39 | ns_xsd["nonNegativeInteger"]: lambda v: _strToBoundNumeral(v, _limits_nonNegativeInteger, int),
40 | ns_xsd["short"]: lambda v: _strToBoundNumeral(v, _limits_short, int),
41 | ns_xsd["unsignedByte"]: lambda v: _strToBoundNumeral(v, _limits_unsignedByte, int),
42 | ns_xsd["unsignedShort"]: lambda v: _strToBoundNumeral(v, _limits_unsignedShort, int),
43 | ns_xsd["unsignedInt"]: lambda v: _strToBoundNumeral(v, _limits_unsignedInt, int),
44 | ns_xsd["unsignedLong"]: lambda v: _strToBoundNumeral(v, _limits_unsignedLong, int),
45 | ns_xsd["hexBinary"]: _strToHexBinary,
46 | ns_xsd["dateTime"]: lambda v: _strToDateTimeAndStamp(v, False),
47 | ns_xsd["dateTimeStamp"]: lambda v: _strToDateTimeAndStamp(v, True),
48 | ns_rdf["XMLLiteral"]: _strToXMLLiteral,
49 | ns_xsd["integer"]: int,
50 | ns_xsd["string"]: lambda v: v,
51 | ns_rdf["HTML"]: lambda v: v,
52 | ns_xsd["normalizedString"]: lambda v: _strToVal_Regexp(v, _re_token),
53 |
54 | # These are RDFS specific...
55 | ns_xsd["time"]: _strToTime,
56 | ns_xsd["date"]: _strToDate,
57 | ns_xsd["gYearMonth"]: _strTogYearMonth,
58 | ns_xsd["gYear"]: _strTogYear,
59 | ns_xsd["gMonthDay"]: _strTogMonthDay,
60 | ns_xsd["gDay"]: _strTogDay,
61 | ns_xsd["gMonth"]: _strTogMonth,
62 | }
63 |
64 | .. seealso:: View the source code :ref:`DatatypeHandling`.
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/test/test_datatypes.py:
--------------------------------------------------------------------------------
1 | """
2 | Test for OWL 2 RL/RDF rules from
3 |
4 | Table 8. The Semantics of Datatypes
5 |
6 | https://www.w3.org/TR/owl2-profiles/#Reasoning_in_OWL_2_RL_and_RDF_Graphs_using_Rules
7 |
8 | NOTE: The following axioms are skipped on purpose
9 |
10 | - dt-eq
11 | - dt-diff
12 | """
13 |
14 | from rdflib import Graph, Literal, Namespace, RDF, XSD, RDFS
15 |
16 | import owlrl
17 |
18 | DAML = Namespace('http://www.daml.org/2002/03/agents/agent-ont#')
19 | T = Namespace('http://test.org/')
20 |
21 | def test_dt_type1():
22 | """
23 | Test dt-type1 rule for OWL 2 RL.
24 | """
25 | g = Graph()
26 | owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g)
27 |
28 | assert (RDF.PlainLiteral, RDF.type, RDFS.Datatype) in g
29 | assert (RDF.XMLLiteral, RDF.type, RDFS.Datatype) in g
30 | assert (RDFS.Literal, RDF.type, RDFS.Datatype) in g
31 | assert (XSD.decimal, RDF.type, RDFS.Datatype) in g
32 | assert (XSD.integer, RDF.type, RDFS.Datatype) in g
33 | assert (XSD.nonNegativeInteger, RDF.type, RDFS.Datatype) in g
34 | assert (XSD.nonPositiveInteger, RDF.type, RDFS.Datatype) in g
35 | assert (XSD.positiveInteger, RDF.type, RDFS.Datatype) in g
36 | assert (XSD.negativeInteger, RDF.type, RDFS.Datatype) in g
37 | assert (XSD.long, RDF.type, RDFS.Datatype) in g
38 | assert (XSD.int, RDF.type, RDFS.Datatype) in g
39 | assert (XSD.short, RDF.type, RDFS.Datatype) in g
40 | assert (XSD.byte, RDF.type, RDFS.Datatype) in g
41 | assert (XSD.unsignedLong, RDF.type, RDFS.Datatype) in g
42 | assert (XSD.unsignedInt, RDF.type, RDFS.Datatype) in g
43 | assert (XSD.unsignedShort, RDF.type, RDFS.Datatype) in g
44 | assert (XSD.unsignedByte, RDF.type, RDFS.Datatype) in g
45 | assert (XSD.float, RDF.type, RDFS.Datatype) in g
46 | assert (XSD.double, RDF.type, RDFS.Datatype) in g
47 | assert (XSD.string, RDF.type, RDFS.Datatype) in g
48 | assert (XSD.normalizedString, RDF.type, RDFS.Datatype) in g
49 | assert (XSD.token, RDF.type, RDFS.Datatype) in g
50 | assert (XSD.language, RDF.type, RDFS.Datatype) in g
51 | assert (XSD.Name, RDF.type, RDFS.Datatype) in g
52 | assert (XSD.NCName, RDF.type, RDFS.Datatype) in g
53 | assert (XSD.NMTOKEN, RDF.type, RDFS.Datatype) in g
54 | assert (XSD.boolean, RDF.type, RDFS.Datatype) in g
55 | assert (XSD.hexBinary, RDF.type, RDFS.Datatype) in g
56 | assert (XSD.base64Binary, RDF.type, RDFS.Datatype) in g
57 | assert (XSD.anyURI, RDF.type, RDFS.Datatype) in g
58 | assert (XSD.dateTime, RDF.type, RDFS.Datatype) in g
59 | assert (XSD.dateTimeStamp, RDF.type, RDFS.Datatype) in g
60 |
61 | def test_dt_type2():
62 | """
63 | Test dt-type2 rule for OWL 2 RL.
64 | """
65 | p_one = Literal(1, datatype=XSD.positiveInteger)
66 |
67 | g = Graph()
68 | g.add((T.A, T.prop, p_one))
69 | owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g)
70 |
71 | assert (T.A, T.prop, p_one) in g
72 | assert (p_one, RDF.type, XSD.positiveInteger) in g
73 |
74 | def test_dt_not_type():
75 | """
76 | Test dt-not-type rule for OWL 2 RL.
77 | """
78 | m_one = Literal(-1, datatype=XSD.nonNegativeInteger)
79 |
80 | g = Graph()
81 | g.add((T.A, T.prop, m_one))
82 | owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g)
83 |
84 | # TODO, we know this one fails. It is not supposed to.
85 | #assert (m_one, RDF.type, XSD.nonNegativeInteger) not in g
86 | assert True
87 |
88 | result = next(g.objects(predicate=DAML.error))
89 | expected = Literal(
90 | 'Lexical value of the literal \'-1\' does not match its datatype'
91 | ' (http://www.w3.org/2001/XMLSchema#nonNegativeInteger)'
92 | )
93 | assert expected == result
94 |
--------------------------------------------------------------------------------
/mimir/src/main/api/shape/ShexResponse.kt:
--------------------------------------------------------------------------------
1 | package api.shape
2 |
3 | import fr.inria.lille.shexjava.schema.ShexSchema
4 | import fr.inria.lille.shexjava.validation.RecursiveValidationWithMemorization
5 | import fr.inria.lille.shexjava.validation.ValidationAlgorithm
6 | import org.apache.commons.rdf.api.Graph
7 | import org.apache.commons.rdf.rdf4j.RDF4J
8 | import org.springframework.http.HttpHeaders
9 | import org.springframework.http.HttpStatus
10 | import org.springframework.http.ResponseEntity
11 | import org.springframework.web.bind.annotation.PostMapping
12 | import org.springframework.web.bind.annotation.RequestBody
13 | import org.springframework.web.bind.annotation.RestController
14 |
15 | import shex.ShexShapeMap
16 | import shex.ShexWrapper
17 |
18 |
19 | data class ShExRequest(
20 | val data: String = "",
21 | val data_lang: String = "TTL",
22 | val shape: String = "",
23 | val shape_map: String = ""
24 | )
25 |
26 | @RestController
27 | class ShexIsValidController {
28 |
29 | @PostMapping(
30 | "/api/shape/shex_isvalid",
31 | consumes = [MimeType.json],
32 | produces = [MimeType.text]
33 | )
34 | fun shexIsValid(@RequestBody requestBody: ShExRequest): ResponseEntity {
35 | val header = HttpHeaders()
36 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text) // all responses are purely on text
37 |
38 | val dataGraph: Graph // data graph
39 | val shape: ShexSchema // shape expression graph
40 | val mapping: List // fixed shape mapping (custom)
41 | val validation: ValidationAlgorithm // validation of the entire data graph
42 | val validationResult: String // validation of the mapping
43 |
44 | if (requestBody.data.isBlank() || requestBody.shape.isBlank() || requestBody.shape_map.isBlank()) {
45 | return ResponseEntity("No Content", header, HttpStatus.NO_CONTENT)
46 | }
47 |
48 | val shexFactory = RDF4J() // Create a factory to be used by ShexJava
49 | val shexWrap = ShexWrapper(shexFactory) // set global factory for ShexJava and start wrapper
50 |
51 | try {
52 | // Load data model as Graph
53 | dataGraph = shexWrap.createDataGraph(requestBody.data, requestBody.data_lang)
54 | } catch (e: Exception) {
55 | return ResponseEntity(
56 | "Data graph ill formed, ${e.message.toString()}", header, HttpStatus.BAD_REQUEST
57 | )
58 | }
59 |
60 | try {
61 | // Load schema to shex java
62 | shape = shexWrap.createSchema(requestBody.shape)
63 | } catch (e: Exception) {
64 | return ResponseEntity(
65 | "Shapes ill formed, ${e.message.toString()}", header, HttpStatus.BAD_REQUEST
66 | )
67 | }
68 |
69 | try {
70 | // Parse Shape map as Pairs with it's corresponding absolute IRIs
71 | mapping = shexWrap.parseMap(requestBody.shape_map)
72 | } catch (e: Exception) {
73 | return ResponseEntity(
74 | "Shape map ill formed, ${e.message.toString()}", header, HttpStatus.BAD_REQUEST
75 | )
76 | }
77 |
78 | try {
79 | // Validate graph and generate result text
80 | validation = RecursiveValidationWithMemorization(shape, dataGraph)
81 | validationResult = shexWrap.validateMapping(validation, mapping)
82 | } catch (e: Exception) {
83 | return ResponseEntity(
84 | "Error generating validation report: ${e.message.toString()}",
85 | header,
86 | HttpStatus.INTERNAL_SERVER_ERROR
87 |
88 | )
89 | }
90 |
91 | // Return validation results
92 | return ResponseEntity(
93 | validationResult, header, HttpStatus.OK
94 | )
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/toc.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | Table of Contents
7 |
8 |
9 |
10 |
11 |
13 | Table of Contents
14 |
15 | Everything
16 |
17 | Modules
18 | RDFClosure RDFClosure.AxiomaticTriples RDFClosure.Closure RDFClosure.CombinedClosure RDFClosure.DatatypeHandling RDFClosure.Literals RDFClosure.OWL' RDFClosure.OWLRL RDFClosure.OWLRLExtras RDFClosure.RDFS' RDFClosure.RDFSClosure RDFClosure.RestrictedDatatype RDFClosure.XsdDatatypes
32 | [hide private ]
34 |
35 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/mimir/src/main/api/shape/SHACLIsValid.kt:
--------------------------------------------------------------------------------
1 | package api.shape
2 |
3 | import toPrintableString
4 | import loadModel
5 | import org.apache.jena.graph.Graph
6 | import org.apache.jena.rdf.model.Model
7 | import org.apache.jena.shacl.ShaclValidator
8 | import org.apache.jena.shacl.Shapes
9 | import org.apache.jena.shacl.ValidationReport
10 | import org.springframework.http.HttpHeaders
11 | import org.springframework.http.HttpStatus
12 | import org.springframework.http.ResponseEntity
13 | import org.springframework.web.bind.annotation.PostMapping
14 | import org.springframework.web.bind.annotation.RequestBody
15 | import org.springframework.web.bind.annotation.RestController
16 | import toDOT
17 |
18 | data class SHACLRequest(
19 | val data: String = "",
20 | val data_lang: String = "TTL",
21 | val shape: String = "",
22 | val shape_lang: String = "TTL"
23 | )
24 |
25 | data class SHACLResponse(
26 | val report: String,
27 | val fusion_dot: String
28 | )
29 |
30 | @RestController
31 | class SHACLIsValidController {
32 |
33 | @PostMapping(
34 | "/api/shape/shacl_isvalid",
35 | consumes = [MimeType.json]
36 | )
37 | fun shaclIsValid(@RequestBody requestBody: SHACLRequest): ResponseEntity {
38 | val header = HttpHeaders()
39 |
40 | // Define the terms outside of try in to use them later
41 | val dataGraph: Graph
42 | val shapesModel: Model
43 | val shapes: Shapes
44 | val fusionDot: String // dot of the union of both graphs
45 | val validationReport: ValidationReport // SCHACL report
46 |
47 | if (requestBody.data.isBlank() || requestBody.shape.isBlank()) {
48 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
49 | return ResponseEntity("No Content", header, HttpStatus.NO_CONTENT)
50 | }
51 |
52 | try {
53 | // Load shape graph
54 | shapesModel = loadModel(requestBody.shape, requestBody.shape_lang)
55 | shapes = Shapes.parse(shapesModel)
56 | } catch (e: Exception) {
57 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
58 | return ResponseEntity("Shapes ill formed, ${e.message.toString()}", header, HttpStatus.BAD_REQUEST)
59 | }
60 |
61 | try {
62 | // Load data graph
63 | dataGraph = loadModel(requestBody.data, requestBody.data_lang).graph
64 | } catch (e: Exception) {
65 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
66 | return ResponseEntity(
67 | "Data graph ill formed, ${e.message.toString()}", header, HttpStatus.BAD_REQUEST
68 | )
69 | }
70 |
71 | try {
72 | // Create DOT with data and shapes
73 | fusionDot = loadModel(requestBody.data, requestBody.data_lang).union(shapesModel).toDOT()
74 | } catch (e: Exception) {
75 | return ResponseEntity(e.message.toString(), header, HttpStatus.BAD_REQUEST)
76 | }
77 |
78 | try {
79 | // Get a validation report
80 | validationReport = ShaclValidator.get().validate(shapes, dataGraph)
81 | } catch (e: Exception) {
82 | // Error trying to make the report
83 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
84 | return ResponseEntity(e.message.toString(), header, HttpStatus.INTERNAL_SERVER_ERROR)
85 | }
86 |
87 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.json)
88 | // default Response as text
89 | return when {
90 | validationReport.conforms() -> {
91 | // Respond "" instead of Conforms\n
92 | ResponseEntity(
93 | SHACLResponse("", fusionDot),
94 | header,
95 | HttpStatus.OK
96 | )
97 | }
98 |
99 | else -> {
100 | // Return complete report as given by Jena
101 | ResponseEntity(
102 | SHACLResponse(validationReport.toPrintableString(), fusionDot),
103 | header,
104 | HttpStatus.OK
105 | )
106 | }
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/mimir/src/test/api/shape/SHACLIsValidControllerTest.kt:
--------------------------------------------------------------------------------
1 | package api.shape
2 |
3 | import org.apache.jena.graph.Graph
4 | import org.apache.jena.rdf.model.Model
5 | import org.apache.jena.shacl.ShaclValidator
6 | import org.apache.jena.shacl.Shapes
7 | import org.apache.jena.shacl.ValidationReport
8 | import org.junit.jupiter.api.Test
9 | import org.junit.jupiter.api.Assertions.*
10 |
11 | import loadModel
12 | import toPrintableString
13 |
14 | internal class SHACLIsValidControllerTest {
15 |
16 | @Test
17 | fun shaclIsValid() {
18 | assertTrue(true)
19 | }
20 |
21 | @Test
22 | fun jenaSHACLDoNotConforms() {
23 | // Generates a valid report without exceptions
24 | val data = """
25 | @prefix : .
26 | @prefix foaf: .
27 | @prefix schema: .
28 |
29 | :dave a :User ; #Fails as a :UserShape
30 | schema:name "Dave";
31 | schema:gender :Unknown ;
32 | schema:birthDate 1980 ;
33 | schema:knows :grace .
34 |
35 | :emily a :User ; #Fails as a :UserShape
36 | schema:name "Emily", "Emilee";
37 | schema:gender schema:Female .
38 |
39 | :frank a :User ; #Fails as a :UserShape
40 | foaf:name "Frank" ;
41 | schema:gender schema:Male .
42 |
43 | _:x a :User; #Fails as a :UserShape
44 | schema:name "Unknown" ;
45 | schema:gender schema:Male ;
46 | schema:knows _:x .
47 | """.trimIndent()
48 | val shape = """
49 | @prefix : .
50 | @prefix foaf: .
51 | @prefix schema: .
52 | @prefix sh: .
53 | @prefix xsd: .
54 |
55 |
56 | :UserShape a sh:NodeShape;
57 | sh:targetClass :User ;
58 | sh:property [ # Blank node 1
59 | sh:path schema:name ;
60 | sh:minCount 1;
61 | sh:maxCount 1;
62 | sh:datatype xsd:string ;
63 | ] ;
64 | sh:property [ # Blank node 2
65 | sh:path schema:gender ;
66 | sh:minCount 1;
67 | sh:maxCount 1;
68 | sh:or (
69 | [ sh:in (schema:Male schema:Female) ]
70 | [ sh:datatype xsd:string]
71 | )
72 | ] ;
73 | sh:property [ # Blank node 3
74 | sh:path schema:birthDate ;
75 | sh:maxCount 1;
76 | sh:datatype xsd:date ;
77 | ] ;
78 | sh:property [ # Blank node 4
79 | sh:path schema:knows ;
80 | sh:nodeKind sh:IRI ;
81 | sh:class :User ;
82 | ] .
83 | """.trimIndent()
84 |
85 | val dataModel: Model = loadModel(data, "TTL")
86 | val shapeModel: Model = loadModel(shape, "TTL")
87 |
88 | val shapes: Shapes = Shapes.parse(shapeModel)
89 | val dataGraph: Graph = dataModel.graph
90 | // get validation report
91 | val validationReport: ValidationReport = ShaclValidator.get().validate(shapes, dataGraph)
92 |
93 | assertNotEquals("Conforms\r\n", validationReport.toPrintableString())
94 | }
95 |
96 | @Test
97 | fun jenaSHACLConforms() {
98 | val data: String = """
99 | @prefix : .
100 | :alice a :User . #Passes as a :UserShape
101 |
102 | a :User . #Passes as a :UserShape
103 | """.trimIndent()
104 | val shape: String = """
105 | @prefix : .
106 | @prefix schema: .
107 | @prefix sh: .
108 | :UserShape a sh:NodeShape;
109 | sh:targetClass :User ;
110 | sh:nodeKind sh:IRI .
111 | """.trimIndent()
112 |
113 | val dataModel: Model = loadModel(data, "TTL")
114 | val shapeModel: Model = loadModel(shape, "TTL")
115 |
116 | val shapes: Shapes = Shapes.parse(shapeModel)
117 | val dataGraph: Graph = dataModel.graph
118 | // get validation report
119 | val validationReport: ValidationReport = ShaclValidator.get().validate(shapes, dataGraph)
120 | assertEquals("Conforms\r\n", validationReport.toPrintableString())
121 | }
122 | }
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/test/relatives.ttl:
--------------------------------------------------------------------------------
1 | @prefix : .
2 | @prefix owl: .
3 | @prefix rdf: .
4 | @prefix xml: .
5 | @prefix xsd: .
6 | @prefix rdfs: .
7 | @base .
8 |
9 | rdf:type owl:Ontology .
10 |
11 | #################################################################
12 | # Object Properties
13 | #################################################################
14 |
15 | ### http://example.org/relatives#hasChild
16 | :hasChild rdf:type owl:ObjectProperty ;
17 | owl:inverseOf :hasParent .
18 |
19 |
20 | ### http://example.org/relatives#hasParent
21 | :hasParent rdf:type owl:ObjectProperty .
22 |
23 | :hasGrandparent rdf:type owl:ObjectProperty ;
24 | owl:propertyChainAxiom ( :hasParent
25 | :hasParent
26 | ) .
27 |
28 | #################################################################
29 | # Classes
30 | #################################################################
31 |
32 | ### http://example.org/relatives#Child
33 | :Child rdf:type owl:Class ;
34 | rdfs:subClassOf :Person .
35 |
36 |
37 | ### http://example.org/relatives#Parent
38 | :Parent rdf:type owl:Class ;
39 | rdfs:subClassOf :Person .
40 |
41 |
42 | ### http://example.org/relatives#Person
43 | :Person rdf:type owl:Class .
44 |
45 |
46 | #################################################################
47 | # Individuals
48 | #################################################################
49 |
50 | ### http://example.org/relatives#Aaron
51 | :Aaron rdf:type owl:NamedIndividual .
52 |
53 |
54 | ### http://example.org/relatives#Ann
55 | :Ann rdf:type owl:NamedIndividual ,
56 | :Person .
57 |
58 |
59 | ### http://example.org/relatives#Bill
60 | :Bill rdf:type owl:NamedIndividual ,
61 | :Person .
62 |
63 |
64 | ### http://example.org/relatives#Bob
65 | :Bob rdf:type owl:NamedIndividual ,
66 | :Person ;
67 | :hasParent :Bill .
68 |
69 |
70 | ### http://example.org/relatives#Cathy
71 | :Cathy rdf:type owl:NamedIndividual ,
72 | :Person ;
73 | :hasParent :Bill .
74 |
75 |
76 | ### http://example.org/relatives#Fred
77 | :Fred rdf:type owl:NamedIndividual ,
78 | :Person ;
79 | :hasChild :James ;
80 | :hasParent :Cathy .
81 |
82 |
83 | ### http://example.org/relatives#Jacob
84 | :Jacob rdf:type owl:NamedIndividual ,
85 | :Person ;
86 | :hasParent :Fred .
87 |
88 |
89 | ### http://example.org/relatives#James
90 | :James rdf:type owl:NamedIndividual ,
91 | :Person .
92 |
93 |
94 | ### http://example.org/relatives#James2
95 | :James2 rdf:type owl:NamedIndividual ,
96 | :Person ;
97 | :hasChild :John .
98 |
99 |
100 | ### http://example.org/relatives#John
101 | :John rdf:type owl:NamedIndividual ,
102 | :Person ;
103 | :hasChild :Mary ,
104 | :Michael ;
105 | :hasParent :James2 .
106 |
107 |
108 | ### http://example.org/relatives#Mary
109 | :Mary rdf:type owl:NamedIndividual ,
110 | :Person .
111 |
112 |
113 | ### http://example.org/relatives#Michael
114 | :Michael rdf:type owl:NamedIndividual ,
115 | :Person ;
116 | :hasParent :John .
117 |
118 |
119 | ### http://example.org/relatives#Simon
120 | :Simon rdf:type owl:NamedIndividual ,
121 | :Person ;
122 | :hasParent :Michael .
123 |
124 |
125 | ### http://example.org/relatives#Tim
126 | :Tim rdf:type owl:NamedIndividual ,
127 | :Person ;
128 | :hasParent :Simon ,
129 | :Valerie .
130 |
131 |
132 | ### http://example.org/relatives#Valerie
133 | :Valerie rdf:type owl:NamedIndividual ,
134 | :Person .
135 |
136 |
137 | ### http://example.org/relatives#Victor
138 | :Victor rdf:type owl:NamedIndividual ,
139 | :Person .
140 |
141 |
142 | ### Generated by the OWL API (version 4.2.8.20170104-2310) https://github.com/owlcs/owlapi
143 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/toc-RDFClosure.RDFS'-module.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | RDFS'
7 |
8 |
9 |
10 |
11 |
13 | Module RDFS'
14 |
15 | Variables
16 | Alt Bag Class Container ContainerMembershipProperty Datatype HTMLLiteral LangString List Literal Property RDFNS RDFSNS Resource Seq Statement XMLLiteral __package__ comment domain first isDefinedBy label member nil object predicate range rest seeAlso subClassOf subPropertyOf subject type value
52 | [hide private ]
54 |
55 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/owlrl/OWL.py:
--------------------------------------------------------------------------------
1 | """
2 | OWL and OWL2 terms. Note that the set of terms is *complete*, I.e., it includes *all* OWL 2 terms, regardless of
3 | whether the term is used in OWL 2 RL or not.
4 |
5 | **Requires**: `RDFLib`_, 4.0.0 and higher.
6 |
7 | .. _RDFLib: https://github.com/RDFLib/rdflib
8 |
9 | **License**: This software is available for use under the `W3C Software License`_.
10 |
11 | .. _W3C Software License: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
12 |
13 | **Organization**: `World Wide Web Consortium`_
14 |
15 | .. _World Wide Web Consortium: http://www.w3.org
16 |
17 | **Author**: `Ivan Herman`_
18 |
19 | .. _Ivan Herman: http://www.w3.org/People/Ivan/
20 | """
21 |
22 |
23 | import rdflib
24 | from rdflib import Namespace
25 |
26 |
27 | # The OWL namespace as used for RDFLib
28 | OWLNS = Namespace("http://www.w3.org/2002/07/owl#")
29 |
30 | annotatedSource = OWLNS["annotatedSource"]
31 | annotatedTarget = OWLNS["annotatedTarget"]
32 | annotatedProperty = OWLNS["annotatedProperty"]
33 | allValuesFrom = OWLNS["allValuesFrom"]
34 | assertionProperty = OWLNS["assertionProperty"]
35 | backwardCompatibleWith = OWLNS["backwardCompatibleWith"]
36 | cardinality = OWLNS["cardinality"]
37 | complementOf = OWLNS["complementOf"]
38 | BottomDataProperty = OWLNS["BottomDataProperty"]
39 | BottomObjectProperty = OWLNS["BottomObjectProperty"]
40 | datatypeComplementOf = OWLNS["datatypeComplementOf"]
41 | deprecated = OWLNS["deprecated"]
42 | differentFrom = OWLNS["differentFrom"]
43 | disjointUnionOf = OWLNS["disjointUnionOf"]
44 | disjointClasses = OWLNS["disjointClasses"]
45 | disjointWith = OWLNS["disjointWith"]
46 | distinctMembers = OWLNS["distinctMembers"]
47 | equivalentClass = OWLNS["equivalentClass"]
48 | equivalentProperty = OWLNS["equivalentProperty"]
49 | hasKey = OWLNS["hasKey"]
50 | hasValue = OWLNS["hasValue"]
51 | hasSelf = OWLNS["hasSelf"]
52 | imports = OWLNS["imports"]
53 | incompatibleWith = OWLNS["incompatibleWith"]
54 | intersectionOf = OWLNS["intersectionOf"]
55 | inverseOf = OWLNS["inverseOf"]
56 | maxCardinality = OWLNS["maxCardinality"]
57 | maxQualifiedCardinality = OWLNS["maxQualifiedCardinality"]
58 | members = OWLNS["members"]
59 | minCardinality = OWLNS["minCardinality"]
60 | minQualifiedCardinality = OWLNS["minQualifiedCardinality"]
61 | onClass = OWLNS["onClass"]
62 | onDataRange = OWLNS["onDataRange"]
63 | onDatatype = OWLNS["onDatatype"]
64 | oneOf = OWLNS["oneOf"]
65 | onProperty = OWLNS["onProperty"]
66 | onProperties = OWLNS["onProperties"]
67 | OWLpredicate = OWLNS["predicate"]
68 | priorVersion = OWLNS["priorVersion"]
69 | propertyChainAxiom = OWLNS["propertyChainAxiom"]
70 | propertyDisjointWith = OWLNS["propertyDisjointWith"]
71 | qualifiedCardinality = OWLNS["qualifiedCardinality"]
72 | sameAs = OWLNS["sameAs"]
73 | someValuesFrom = OWLNS["someValuesFrom"]
74 | sourceIndividual = OWLNS["sourceIndividual"]
75 | OWLsubject = OWLNS["subject"]
76 | targetIndividual = OWLNS["targetIndividual"]
77 | targetValue = OWLNS["targetValue"]
78 | TopDataProperty = OWLNS["TopDataProperty"]
79 | TopObjectProperty = OWLNS["TopObjectProperty"]
80 | unionOf = OWLNS["unionOf"]
81 | versionInfo = OWLNS["versionInfo"]
82 | versionIRI = OWLNS["versionIRI"]
83 | withRestrictions = OWLNS["withRestrictions"]
84 |
85 | AllDisjointProperties = OWLNS["AllDisjointProperties"]
86 | AllDifferent = OWLNS["AllDifferent"]
87 | AllDisjointClasses = OWLNS["AllDisjointClasses"]
88 | Annotation = OWLNS["Annotation"]
89 | AnnotationProperty = OWLNS["AnnotationProperty"]
90 | AsymmetricProperty = OWLNS["AsymmetricProperty"]
91 | Axiom = OWLNS["Axiom"]
92 | OWLClass = OWLNS["Class"]
93 | DataRange = OWLNS["DataRange"]
94 | DatatypeProperty = OWLNS["DatatypeProperty"]
95 | DeprecatedClass = OWLNS["DeprecatedClass"]
96 | DeprecatedProperty = OWLNS["DeprecatedProperty"]
97 | FunctionalProperty = OWLNS["FunctionalProperty"]
98 | InverseFunctionalProperty = OWLNS["InverseFunctionalProperty"]
99 | IrreflexiveProperty = OWLNS["IrreflexiveProperty"]
100 | NamedIndividual = OWLNS["NamedIndividual"]
101 | NegativePropertyAssertion = OWLNS["NegativePropertyAssertion"]
102 | Nothing = OWLNS["Nothing"]
103 | ObjectProperty = OWLNS["ObjectProperty"]
104 | Ontology = OWLNS["Ontology"]
105 | OntologyProperty = OWLNS["OntologyProperty"]
106 | ReflexiveProperty = OWLNS["ReflexiveProperty"]
107 | Restriction = OWLNS["Restriction"]
108 | Thing = OWLNS["Thing"]
109 | SelfRestriction = OWLNS["SelfRestriction"]
110 | SymmetricProperty = OWLNS["SymmetricProperty"]
111 | TransitiveProperty = OWLNS["TransitiveProperty"]
112 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/owlrl/XsdDatatypes.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | """
4 | Lists of XSD datatypes and their mutual relationships
5 |
6 | **Requires**: `RDFLib`_, 4.0.0 and higher.
7 |
8 | .. _RDFLib: https://github.com/RDFLib/rdflib
9 |
10 | **License**: This software is available for use under the `W3C Software License`_.
11 |
12 | .. _W3C Software License: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
13 |
14 | **Organization**: `World Wide Web Consortium`_
15 |
16 | .. _World Wide Web Consortium: http://www.w3.org
17 |
18 | **Author**: `Ivan Herman`_
19 |
20 | .. _Ivan Herman: http://www.w3.org/People/Ivan/
21 |
22 | """
23 | __author__ = 'Ivan Herman'
24 | __contact__ = 'Ivan Herman, ivan@w3.org'
25 | __license__ = 'W3C® SOFTWARE NOTICE AND LICENSE, http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231'
26 |
27 | # noinspection PyPep8Naming
28 | from .RDFS import RDFNS as ns_rdf
29 | from .RDFS import Literal
30 | from .RDFS import XMLLiteral
31 | from .RDFS import HTMLLiteral
32 | from .RDFS import LangString
33 |
34 | import rdflib
35 | # noinspection PyPep8Naming
36 | from rdflib.namespace import XSD as ns_xsd
37 |
38 | #: The basic XSD types used everywhere; this means not the complete set of day/month types
39 | _Common_XSD_Datatypes = [
40 | ns_xsd['integer'], ns_xsd['decimal'], ns_xsd['nonNegativeInteger'], ns_xsd['nonPositiveInteger'],
41 | ns_xsd['negativeInteger'], ns_xsd['positiveInteger'], ns_xsd['long'], ns_xsd['int'], ns_xsd['short'],
42 | ns_xsd['byte'], ns_xsd['unsignedLong'], ns_xsd['unsignedInt'], ns_xsd['unsignedShort'],
43 | ns_xsd['unsignedByte'], ns_xsd['float'], ns_xsd['double'], ns_xsd['string'], ns_xsd['normalizedString'],
44 | ns_xsd['token'], ns_xsd['language'], ns_xsd['Name'], ns_xsd['NCName'], ns_xsd['NMTOKEN'],
45 | ns_xsd['boolean'], ns_xsd['hexBinary'], ns_xsd['base64Binary'], ns_xsd['anyURI'],
46 | ns_xsd['dateTimeStamp'], ns_xsd['dateTime'], ns_xsd['time'], ns_xsd['date'],
47 | Literal, XMLLiteral, HTMLLiteral, LangString
48 | ]
49 |
50 | #: RDFS Datatypes: the basic ones plus the complete set of day/month ones
51 | RDFS_Datatypes = _Common_XSD_Datatypes + [ns_xsd['gYearMonth'], ns_xsd['gMonthDay'], ns_xsd['gYear'],
52 | ns_xsd['gDay'], ns_xsd['gMonth']]
53 |
54 | #: OWL RL Datatypes: the basic ones plus plain literal
55 | OWL_RL_Datatypes = _Common_XSD_Datatypes + [ns_rdf['PlainLiteral']]
56 |
57 | #: XSD Datatype subsumptions
58 | _Common_Datatype_Subsumptions = {
59 | ns_xsd['dateTimeStamp']: [ns_xsd['dateTime']],
60 | ns_xsd['integer']: [ns_xsd['decimal']],
61 | ns_xsd['long']: [ns_xsd['integer'], ns_xsd['decimal']],
62 | ns_xsd['int']: [ns_xsd['long'], ns_xsd['integer'], ns_xsd['decimal']],
63 | ns_xsd['short']: [ns_xsd['int'], ns_xsd['long'], ns_xsd['integer'], ns_xsd['decimal']],
64 | ns_xsd['byte']: [ns_xsd['short'], ns_xsd['int'], ns_xsd['long'], ns_xsd['integer'], ns_xsd['decimal']],
65 |
66 | ns_xsd['nonNegativeInteger']: [ns_xsd['integer'], ns_xsd['decimal']],
67 | ns_xsd['positiveInteger']: [ns_xsd['nonNegativeInteger'], ns_xsd['integer'], ns_xsd['decimal']],
68 | ns_xsd['unsignedLong']: [ns_xsd['nonNegativeInteger'], ns_xsd['integer'], ns_xsd['decimal']],
69 | ns_xsd['unsignedInt']: [ns_xsd['unsignedLong'], ns_xsd['nonNegativeInteger'], ns_xsd['integer'], ns_xsd['decimal']],
70 | ns_xsd['unsignedShort']: [ns_xsd['unsignedInt'], ns_xsd['unsignedLong'], ns_xsd['nonNegativeInteger'],
71 | ns_xsd['integer'], ns_xsd['decimal']],
72 | ns_xsd['unsignedByte']: [ns_xsd['unsignedShort'], ns_xsd['unsignedInt'], ns_xsd['unsignedLong'],
73 | ns_xsd['nonNegativeInteger'], ns_xsd['integer'], ns_xsd['decimal']],
74 |
75 | ns_xsd['nonPositiveInteger']: [ns_xsd['integer'], ns_xsd['decimal']],
76 | ns_xsd['negativeInteger']: [ns_xsd['nonPositiveInteger'], ns_xsd['integer'], ns_xsd['decimal']],
77 |
78 | ns_xsd['normalizedString']: [ns_xsd["string"]],
79 | ns_xsd['token']: [ns_xsd['normalizedString'], ns_xsd["string"]],
80 | ns_xsd['language']: [ns_xsd['token'], ns_xsd['normalizedString'], ns_xsd["string"]],
81 | ns_xsd['Name']: [ns_xsd['token'], ns_xsd['normalizedString'], ns_xsd["string"]],
82 | ns_xsd['NCName']: [ns_xsd['Name'], ns_xsd['token'], ns_xsd['normalizedString'], ns_xsd["string"]],
83 | ns_xsd['NMTOKEN']: [ns_xsd['Name'], ns_xsd['token'], ns_xsd['normalizedString'], ns_xsd["string"]],
84 | }
85 |
86 | #: RDFS Datatype subsumptions: at the moment, there is no extra to XSD
87 | RDFS_Datatype_Subsumptions = _Common_Datatype_Subsumptions
88 |
89 | #: OWL Datatype subsumptions: at the moment, there is no extra to XSD
90 | OWL_Datatype_Subsumptions = _Common_Datatype_Subsumptions
91 |
--------------------------------------------------------------------------------
/mimir/README.md:
--------------------------------------------------------------------------------
1 | ## Set up and running
2 | The backend is written on Kotlin using Spring Boot framework, dependencies and
3 | configurations are done using Maven, so you should install that before.
4 |
5 | However, given that it also uses BastyZ/OWL-RL instead of RDFLib/OWL-RL, you
6 | must set up and environment before launching the backend.
7 |
8 | ⚠ For this to work you should use Python 3.5+ and Pip
9 |
10 | Go to `src/main/reasoner/owlrl` and create a virtualenv (we use _venv_) according to
11 | [venv documentation](https://docs.python.org/3/library/venv.html) and install BastyZ/OWL-RL:
12 | ```shell script
13 | # Create venv environment
14 | python3 -m venv venv
15 |
16 | # Activate
17 | source venv/bin/activate
18 |
19 | # Install BastyZ/OWL-RL on the current environment
20 | python setup.py install
21 |
22 | ```
23 |
24 | Having _maven_ installed, write on your terminal:
25 |
26 | ``` shell script
27 | # install dependencies
28 | mvn install
29 | ```
30 |
31 | And you can run it with:
32 |
33 | ``` shell script
34 | # Activate venv before running SpringBoot
35 | source src/main/reasoner/owlrl/venv/bin/activate
36 |
37 | mvn spring-boot:run
38 | ```
39 |
40 | ## Configuration
41 | ### Port
42 | Go to `src/main/resources` and edit the file `application.yml`, modifying:
43 | ``` sh
44 | port : 9060
45 | ```
46 |
47 | You can modify a lot of things here, see
48 | [this documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-yaml)
49 | to learn more.
50 |
51 | ### CORS
52 | This API only accepts request from accepted origins, this is added like several
53 | mappings, defining controllers, origins, methods and timeouts. Edit the file
54 | `WebConfig.kt` at `src/main/api/` adding or editing existing mappings.
55 |
56 | A mapping looks like:
57 | ``` Kotlin
58 | // Based on https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-cors-global
59 | registry.addMapping("/api/**")
60 | .allowedOrigins("http://localhost:9080")
61 | .allowedMethods("GET", "POST")
62 | .maxAge(3600)
63 | ```
64 |
65 | ### OWL 2 RL / RDFS Reasoners
66 | The backend contains a full copy of
67 | [OWL-RL](https://github.com/BastyZ/OWL-RL)
68 | written on python 3 on the directory `src/main/reasoner/owlrl`, to run the
69 | `script/owlrl` CLI script.
70 |
71 | Our OWL-RL wrapper (on `OwlRLWrapper.kt:38`) executes the following configuration
72 | elements to infer using BastyZ/OWL-RL where **flag** is either -r or -w for RDFS and OWL
73 | respectively:
74 |
75 | ```shell script
76 | CMD_NAME flag -f
77 | ```
78 |
79 | Then read the Runtime CLI for the inference result, and converts this result to DOT.
80 |
81 | #### Modify OWL-RL location or version
82 |
83 | If you want to upgrade it or use another version of OWL-RL you can place it on the
84 | same place and configuring the environment again, or change the
85 | `ReasonerConfig.kt` file on the `src/main/api/` directory, to change where
86 | the runtime looks for an environment, and the script (lines 10 and 11).
87 |
88 | ``` Kotlin
89 | # Activations script is not being used right now, because the runtime will get a denied access
90 | var ENV_ACTIVATION_SCRIPT = "source src/main/reasoner/owlrl/venv/bin/activate"
91 | var CMD_NAME = "python src/main/reasoner/owlrl/scripts/owlrl"
92 | ```
93 |
94 | Pointing to the same script on another place you desire.
95 |
96 | #### Configure an environment for OWL-RL
97 | This configuration is exactly the same that the one on the initial setup.
98 |
99 | Go to `src/main/reasoner/owlrl` and create a virtualenv (we use _venv_) according to
100 | [venv documentation](https://docs.python.org/3/library/venv.html):
101 | ```shell script
102 | # Create venv environment
103 | python3 -m venv venv
104 |
105 | # Activate on Windows systems (See configuration section for more info)
106 | venv/Scripts/activate.bat
107 | # for Linux based systems (default configuration)
108 | source venv/bin/activate
109 |
110 | # Install BastyZ/OWL-RL on the current environment
111 | python setup.py install
112 |
113 | ```
114 |
115 | ## Directories
116 | This project is divided on the following way:
117 | ```
118 | src/main
119 | |
120 | + -- api # API controllers and code
121 | | |
122 | | + -- model # api/model endpoints
123 | | |
124 | | + -- owl # api/owl endpoints
125 | | |
126 | | + -- shape # api/shape endpoints
127 | | |
128 | | + -- tdb # api/tdb endpoints
129 | | |
130 | | + -- Application.kt # App main()
131 | |
132 | + -- dot # DOT writter extension for Jena
133 | |
134 | + -- reasoner # OWL-RL sources copy, wrapper and temp directory
135 | |
136 | + -- shex # ShEx Wrapper, map extension and temp directory
137 | |
138 | + -- Utils.kt # Auxiliary functions
139 | ```
140 |
141 |
142 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/scripts/owlrl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | from optparse import OptionParser
5 | from owlrl import convert_graph, RDFXML, TURTLE, JSON, AUTO, RDFA
6 |
7 |
8 | def main():
9 | parser = OptionParser(usage="%prog [options] fname1 fname2 ...")
10 | parser.disable_interspersed_args()
11 |
12 | # The 'text' field is not used in the command line, but the CGI environment uses it. This means that there
13 | # is no option to change that, but is added to the final option structure
14 | parser.set_defaults(format=TURTLE, owlClosure="no", rdfsClosure="no", owlExtras="no", axioms="no", daxioms="no",
15 | iformat=AUTO, trimming="no", maximal="no", text=None)
16 |
17 | parser.add_option("-f", "--file", type="string", dest="source",
18 | help="input file; should be a .rdf or .ttl file, for RDF/XML or Turtle, respectively. If "
19 | "missing, or if the value is '-' then standard input is used. Usage of this options is not "
20 | "really necessary, the fname in the command lines refer to files by themselves")
21 |
22 | parser.add_option("--owlrl", action="store", dest="owlClosure", choices=["yes", "no"],
23 | help="execute OWL RL closure; argument must be yes|no [default: %default]")
24 |
25 | parser.add_option("-w", action="store_const", dest="owlClosure", const="yes",
26 | help="OWL-RL is executed; shorthand for --owlrl=yes")
27 |
28 | parser.add_option("--rdfs", action="store", dest="rdfsClosure", choices=["yes", "no"],
29 | help="execute RDFS closure; argument must be yes|no [default: %default]")
30 |
31 | parser.add_option("-r", action="store_const", dest="rdfsClosure", const="yes",
32 | help="RDFS is executed; shorthand for --rdfs=yes")
33 |
34 | parser.add_option("--extras", action="store", dest="owlExtras", choices=["yes", "no"],
35 | help="additional owl features added; argument must be yes|no [default: %default]")
36 |
37 | parser.add_option("-e", action="store_const", dest="owlExtras", const="yes",
38 | help="additional owl features added; shorthand for --extras=yes [default: %default]")
39 |
40 | parser.add_option("--axioms", action="store", dest="axioms", choices=["yes", "no"],
41 | help="axiomatic triples; argument must be yes|no [default: %default]")
42 |
43 | parser.add_option("-a", action="store_const", dest="axioms", const="yes",
44 | help="add axiomatic triples; shorthand for --axioms=yes [default: %default]")
45 |
46 | parser.add_option("--daxioms", action="store", dest="daxioms", choices=["yes", "no"],
47 | help="datatype axiomatic triples; argument must be true|false [default: %default]")
48 |
49 | parser.add_option("-d", action="store_const", dest="daxioms", const="yes",
50 | help="add axiomatic triples; shorthand for --daxioms=yes [default: %default]")
51 |
52 | parser.add_option("--trimming", action="store", dest="trimming", choices=["yes", "no"],
53 | help="trim the output of OWL 2 RL and extension; 'yes' is ineffective unless --extras=yes "
54 | "[default: %default]")
55 |
56 | parser.add_option("-m", "--maximal", action="store_const", dest="maximal", const="yes",
57 | help="maximal possibilities switched on: RDFS, OWL with extensions, and with trimming")
58 |
59 | parser.add_option("-t", action="store_const", dest="trimming", const="yes",
60 | help="trim the output of OWL 2 RL and extension; shorthand for --trimming=yes "
61 | "[default: %default]")
62 |
63 | parser.add_option("-o", "-s", "--serialization", "--syntax", action="store", dest="format",
64 | choices=[TURTLE, JSON, RDFXML],
65 | help="output format; argument must be turtle|json|xml [default: %default]")
66 |
67 | parser.add_option("-i", "--input_syntax", action="store", dest="iformat",
68 | choices=[AUTO, TURTLE, JSON, RDFA, RDFXML],
69 | help="format of input; argument must be auto|turtle|xml|rdfa|json [default: %default]; auto "
70 | "means that file suffix defines the format. This flag is valid for all input files.")
71 |
72 | (options, args) = parser.parse_args()
73 | if options.source is None:
74 | options.sources = []
75 | else:
76 | options.sources = [options.source]
77 |
78 | if len(args) > 0:
79 | options.sources += args
80 |
81 | if len(options.sources) == 0:
82 | # the default mechanism, ie, to use standard input
83 | options.sources = ["-"]
84 |
85 | if options.maximal == "yes":
86 | options.trimming = "yes"
87 | options.owlClosure = "yes"
88 | options.owlExtras = "yes"
89 |
90 | print(convert_graph(options))
91 |
92 |
93 | # The standard startup idiom...
94 | if __name__ == '__main__':
95 | main()
96 |
--------------------------------------------------------------------------------
/mimir/src/main/api/tdb/QueryModelResponse.kt:
--------------------------------------------------------------------------------
1 | package api.tdb
2 |
3 | import org.apache.jena.query.*
4 | import org.apache.jena.rdf.model.Model
5 | import org.apache.jena.rdf.model.ModelFactory.createDefaultModel
6 | import org.springframework.http.ResponseEntity
7 | import org.springframework.http.HttpHeaders
8 | import org.springframework.http.HttpStatus
9 | import org.springframework.http.MediaType
10 | import org.springframework.web.bind.annotation.PostMapping
11 | import org.springframework.web.bind.annotation.RequestBody
12 | import org.springframework.web.bind.annotation.RequestHeader
13 | import org.springframework.web.bind.annotation.RestController
14 |
15 | import formatAs
16 | import formatAskAs
17 | import loadModel
18 | import parseFormat
19 | import toDOT
20 | import toMimeType
21 | import api.tdb.sparqlPatternToDot
22 |
23 |
24 | data class QueryModelRequest(
25 | val data: String = "",
26 | val data_lang: String = "TTL",
27 | val query: String = "",
28 | val query_response_lang:String = ""
29 | )
30 |
31 | fun pickFormat(formats: MutableList): String {
32 | return when (formats.size) {
33 | 0 -> "No Format"
34 | 1 -> formats.first()
35 | else -> {
36 | // We always expect to receive Text and Another format,
37 | // so we pick the other one
38 | if (formats.filterNot { it == "Text" }.isEmpty()) return "Text"
39 | else formats
40 | .filterNot { it == "Text" }
41 | .first()
42 | }
43 | }
44 |
45 | }
46 |
47 | @RestController
48 | class QueryModelController {
49 |
50 | @PostMapping(
51 | "/api/tdb/query_model",
52 | consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE]
53 | )
54 | fun queryModel(
55 | @RequestHeader(HttpHeaders.ACCEPT) formats: String,
56 | @RequestBody request: QueryModelRequest
57 | ): ResponseEntity {
58 | val responseLangOptions = parseFormat(formats)
59 | var responseLang = pickFormat(responseLangOptions)
60 | val header = HttpHeaders()
61 |
62 | // no info case
63 | if (request.data.isBlank()) {
64 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
65 | return ResponseEntity("No Content", header, HttpStatus.NO_CONTENT)
66 | }
67 |
68 | // load model to Memory
69 | val model: Model
70 | try {
71 | model = loadModel(request.data, request.data_lang)
72 | val dataOnDOT: String = model.toDOT()
73 | } catch (e: Exception) {
74 | // could not load model by some reason
75 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
76 | return ResponseEntity("Can't read model", header, HttpStatus.BAD_REQUEST)
77 | }
78 | val query: Query
79 |
80 | try {
81 | // Query that model
82 | query = QueryFactory.create(request.query)
83 | } catch (e: Exception) {
84 | // could not load model by some reason
85 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
86 | return ResponseEntity("Can't run query: \n Reason: ${e.message}", header, HttpStatus.BAD_REQUEST)
87 | }
88 |
89 | var queryResponseBody = String()
90 | var response_type:String = request.query_response_lang
91 | if (response_type == "Query") {
92 | queryResponseBody = sparqlPatternToDot(request.query)
93 | }
94 | else {
95 | try {
96 | QueryExecutionFactory.create(query, model).let { qExecution: QueryExecution ->
97 | when {
98 | query.isSelectType -> {
99 | val resultSet: ResultSet = qExecution.execSelect()
100 | queryResponseBody = resultSet.formatAs(responseLang)
101 | }
102 | query.isAskType -> {
103 | val resultSet: Boolean = qExecution.execAsk()
104 | queryResponseBody = resultSet.formatAskAs(responseLang)
105 | }
106 | query.isConstructType or query.isDescribeType -> {
107 | val resultModel: Model = when {
108 | query.isConstructType -> qExecution.execConstruct()
109 | query.isDescribeType -> qExecution.execDescribe()
110 | else -> createDefaultModel() // Should not be possible, but when is exhaustive
111 | }
112 | // Format to response, defaults to TTL
113 | val responsePair: Pair = resultModel.formatAs(responseLang)
114 | queryResponseBody = responsePair.first
115 | responseLang = responsePair.second
116 | }
117 | }
118 | }
119 | } catch (e: Exception) {
120 | // Return an error response
121 | header.add(HttpHeaders.CONTENT_TYPE, MimeType.text)
122 | return ResponseEntity("Unsupported Media type / Format", header, HttpStatus.UNSUPPORTED_MEDIA_TYPE)
123 | }
124 | }
125 | header.add(HttpHeaders.CONTENT_TYPE, toMimeType(responseLang))
126 | return ResponseEntity(queryResponseBody, header, HttpStatus.OK)
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RDF Playground
2 | This project allows web users to write RDF as Turtle, check its syntax,
3 | visualize the data as a graph, and use SPARQL, RDFS, OWL, SHACL and ShEx.
4 |
5 | The project is intended to provide many functionalities in one system,
6 | and is intended to be used for small examples (e.g., for teaching or demos).
7 |
8 | You can see a [demo here](http://rdfplayground.dcc.uchile.cl/). Note that the
9 | demo is not intended to be a production system. If you intend to use RDF Playground
10 | regularly (e.g., for a class), we would recommend to install and run it locally in a
11 | server you control. There are two options: direct or Docker.
12 |
13 | # Installation and running (direct)
14 |
15 | Ensure you've cloned or downloaded this repository on the machine you want to run RDF Playground. You will need to install and run the back-end (Mimir) and the front-end (Odin) for RDF Playground to run.
16 |
17 | ### Back end (mimir folder)
18 | The backend is written in Kotlin using the Spring Boot framework; dependencies and
19 | configurations are done using Maven. The code also has [a fork](https://github.com/BastyZ/OWL-RL) of the (Python) [OWL-RL reasoner](https://github.com/RDFLib/OWL-RL)
20 | inside, so you have to create and environment for this code before executing the backend.
21 |
22 | ⚠ For this to work you should use Python 3.5+ and Pip
23 |
24 | Go to `src/main/reasoner/owlrl` and create a virtualenv (we use _venv_) according to
25 | [venv documentation](https://docs.python.org/3/library/venv.html) and install BastyZ/OWL-RL:
26 | ```shell script
27 | # Create venv environment
28 | python3 -m venv venv
29 |
30 | # Activate
31 | source venv/bin/activate
32 |
33 | # Install BastyZ/OWL-RL on the current environment
34 | python setup.py install
35 | ```
36 |
37 | Then, having _maven_ installed, you go to `mimir/` directory where `pom.xml` is and
38 | write in your terminal:
39 |
40 | ``` sh
41 | # install dependencies
42 | mvn install
43 | ```
44 |
45 | And you can run it with:
46 |
47 | ``` sh
48 | # Activate venv before running SpringBoot
49 | source src/main/reasoner/owlrl/venv/bin/activate
50 |
51 | mvn spring-boot:run
52 | ```
53 |
54 | ### Front end (odin folder)
55 | The frontend is written in Javascript + HTML using Vuetify framework and nodejs
56 | 13; having that and npm installed you can go to the `odin/` directory and write:
57 |
58 | ``` sh
59 | # install dependencies
60 | npm install
61 | ```
62 |
63 | And you can run it with:
64 | ``` sh
65 | # run for development
66 | npm run-script serve
67 |
68 | # create a production build
69 | npm run-script build
70 | ```
71 | This last command produces a production-ready bundle in the `dist/` directory,
72 | see https://cli.vuejs.org/guide/cli-service.html#vue-cli-service-build for more
73 | information.
74 |
75 | For more information on the serve command see
76 | https://cli.vuejs.org/guide/cli-service.html#vue-cli-service-serve.
77 |
78 | ### Configuration
79 | For configurations on the backend and frontend see their respective README
80 | files.
81 |
82 | # Installation and running (Docker)
83 |
84 | Ensure you've cloned or downloaded this repository on the machine you want to run RDF Playground.
85 |
86 | The repository also provides a `Dockerfile` that facilitates installing and running RDF Playground in Docker (credit to [@fvillena](https://github.com/fvillena)).
87 |
88 | Ensure that Docker is installed and running ([see instructions](https://docs.docker.com/engine/install/)).
89 |
90 | The following commands assume a Unix-like environment. **Some commands may need `sudo` depending on how you've installed and run Docker.**
91 |
92 | With Docker running, go to the RDFPlayground main folder (the one containing `Dockerfile`):
93 |
94 | ```sh
95 | cd /path/to/RDFPlayground
96 | ```
97 |
98 | Next we build a Docker image:
99 |
100 | ```sh
101 | docker build -t rdf-playground .
102 | ```
103 |
104 | This might take some time. The final Docker image should be around 1GB. Once installed you can run
105 |
106 | ```sh
107 | sudo docker image list
108 | ```
109 |
110 | Where you should see the `rdf-playground` image listed.
111 |
112 | Next we need to run a Docker container for RDF Playground. Here we assume that we want to map between port `80` of the container for the front-end to port `80` of the `localhost` of the machine running Docker (the first `80` is the port of the machine; the second `80` is the port of the container) and port `9060` of the container for the back-end to port `9060` of the `localhost` of the machine. We also assume that we want to restart RDF Playground if for any reason it is not running with the `always` option ([see more options](https://docs.docker.com/config/containers/start-containers-automatically/)).
113 |
114 | ```sh
115 | docker run -d -p 127.0.0.1:80:80 -p 127.0.0.1:9060:9060 --restart always rdf-playground
116 | ```
117 |
118 | You should now see the container running with:
119 |
120 | ```sh
121 | docker ps
122 | ```
123 |
124 | If this worked, you should be able to call (in the case of port `80` on the machine, otherwise adding `:1234` without space if using port `1234` on the machine):
125 |
126 | ```sh
127 | wget localhost
128 | ```
129 |
130 | This should download a HTML file, which you can preview with:
131 |
132 | ```sh
133 | more index.html
134 | ```
135 |
136 | It may indicate that Javascript is not running, but this should not be a problem once you load the page from the browser.
137 |
138 | Now RDF Playground should be running on the selected port of your machine. (You may still need to configure external Web access via a static I.P. or hostname to the selected port on your machine.)
139 |
140 | Copyright © 2020 Bastián Inostroza, Licensed under the Apache License, Version 2.0.
141 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/scripts/RDFConvertService:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Possible CGI entry point for the owl package.
5 |
6 | @author: U{Ivan Herman}
7 | @license: This software is available for use under the
8 | U{W3C® SOFTWARE NOTICE AND LICENSE}
9 | @contact: Ivan Herman, ivan@w3.org
10 | """
11 |
12 | """
13 | $Id: RDFConvertService.py,v 1.3 2009/07/10 08:45:14 ivan Exp $
14 | """
15 |
16 | import os
17 | import sys
18 | import cgi
19 | import cgitb
20 | # prevent accidentally importing `scripts/owlrl` file when calling
21 | # `from owlrl import ...` below.
22 | HERE_DIR = os.path.abspath(os.path.dirname(__file__))
23 | if HERE_DIR in sys.path:
24 | sys.path.remove(HERE_DIR)
25 |
26 | # Add 'owlrl' module from the parent directory into the path if it exists.
27 | PARENT_DIR = os.path.dirname(HERE_DIR)
28 | parent_dir_list = os.listdir(PARENT_DIR)
29 | if 'owlrl' in parent_dir_list:
30 | possible_owlrl = os.path.join(PARENT_DIR, 'owlrl')
31 | if os.path.isdir(possible_owlrl):
32 | sys.path.append(possible_owlrl)
33 |
34 | __version__ = "4.0"
35 | cgitb.enable()
36 | form = cgi.FieldStorage()
37 | from owlrl import convert_graph, RDFXML, TURTLE, AUTO
38 |
39 | # ---------------------------------------------------------------------------------------------------------------------
40 |
41 |
42 | class Options:
43 | def __init__(self, frm):
44 | self.iformat = AUTO
45 | self.owlClosure = "no"
46 | self.rdfsClosure = "no"
47 | self.owlExtras = "no"
48 | self.axioms = "no"
49 | self.daxioms = "no"
50 | self.sources = []
51 | self.text = None
52 | self.format = TURTLE
53 |
54 | if "source_1" in list(frm.keys()):
55 | self.sources.append(frm["source_1"].value)
56 | if "source_2" in list(frm.keys()):
57 | self.sources.append(frm["source_2"].value)
58 |
59 | if "text" in list(frm.keys()):
60 | self.text = frm["text"].value
61 | if "format" in list(frm.keys()):
62 | self.format = frm["format"].value
63 | if "iformat" in list(frm.keys()):
64 | v = frm["iformat"].value
65 | if v == "xml" or v == "turtle":
66 | self.iformat = v
67 |
68 | if "fullClosure" in list(frm.keys()) and frm["fullClosure"].value == "yes":
69 | self.owlClosure = "yes"
70 | self.rdfsClosure = "yes"
71 | self.axioms = "no"
72 | self.daxioms = "no"
73 | self.owlExtras = "no"
74 | else:
75 | if "owlClosure" in list(frm.keys()):
76 | self.owlClosure = frm["owlClosure"].value
77 | if "rdfsClosure" in list(frm.keys()):
78 | self.rdfsClosure = frm["rdfsClosure"].value
79 | if "owlExtras" in list(frm.keys()):
80 | self.owlExtras = frm["owlExtras"].value
81 | if "axioms" in list(frm.keys()):
82 | self.axioms = frm["axioms"].value
83 | if "daxioms" in list(frm.keys()):
84 | self.daxioms = frm["daxioms"].value
85 |
86 | # this one is for backward compatibility...
87 | if "uri" in list(frm.keys()):
88 | self.sources.append(frm["uri"].value)
89 | if "source" in list(frm.keys()):
90 | self.sources.append(frm["source"].value)
91 |
92 | def to_html(self):
93 | print('')
94 |
95 | print('Sources: ')
96 | print('')
97 | if len(self.sources) == 0:
98 | print("none")
99 | elif len(self.sources) == 1:
100 | print(cgi.escape(self.sources[0]))
101 | else:
102 | print(cgi.escape(self.sources[0]), ", ", cgi.escape(self.sources[1]))
103 | print(' ')
104 |
105 | print('Input format: ')
106 | print('%s ' % self.iformat)
107 | print('Output format: %s ' % self.format)
108 | print('OWL 2 RL Processing: %s ' % self.owlClosure)
109 | print('RDFS Processing: %s ' % self.rdfsClosure)
110 | print('Extra OWL Processing: %s ' % self.owlExtras)
111 | print('Axiomatic triples added: %s ' % self.axioms)
112 | print('Datatype Axiomatic triples added: %s ' % self.daxioms)
113 | if self.text is not None:
114 | print('Turtle code added to the graph: ')
115 | print('')
116 | if self.text is not None:
117 | print(cgi.escape(self.text).replace('\n', ' '))
118 |
119 | # ---------------------------------------------------------------------------------------------------------------------
120 |
121 |
122 | options = Options(form)
123 |
124 | try:
125 | retval = convert_graph(options)
126 | if options.format == TURTLE:
127 | print('Content-Type: text/turtle; charset=utf-8')
128 | else:
129 | print('Content-Type: application/rdf+xml; charset=utf-8')
130 | print()
131 | print(retval)
132 | except:
133 | (typ, value, traceback) = sys.exc_info()
134 | print('Content-type: text/html; charset=utf-8')
135 | print('Status: 400 Invalid Input')
136 | print()
137 | print("")
138 | print("")
139 | print("Error in RDF Closure processing ")
140 | print("")
141 | print("Error in RDF Closure processing: ")
142 | print("%s " % value)
143 | print("For reference, the input arguments were: ")
144 | options.to_html()
145 | print("")
146 | print("")
147 |
--------------------------------------------------------------------------------
/mimir/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 | bastyz
7 | linkeddata
8 | 1.0-SNAPSHOT
9 | jar
10 |
11 | mimir
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.3.1.RELEASE
17 |
18 |
19 |
20 | UTF-8
21 | 1.4.10
22 | official
23 | 1.8
24 | 1.4.0-M1
25 | 4.13
26 | 5.6.2
27 | 3.14.0
28 | 2.1.8.RELEASE
29 | 1.2.3
30 | 1.8
31 |
32 |
33 |
34 |
35 | org.jetbrains.kotlin
36 | kotlin-stdlib
37 | ${kotlin.version}
38 |
39 |
40 | org.apache.jena
41 | apache-jena-libs
42 | pom
43 | ${jena.version}
44 |
45 |
46 | org.apache.jena
47 | jena-text
48 | ${jena.version}
49 |
50 |
51 | org.jetbrains.kotlin
52 | kotlin-test-junit
53 | ${kotlin.version}
54 | test
55 |
56 |
57 |
58 | org.jetbrains.kotlinx
59 | kotlinx-coroutines-core
60 | ${kotlinx.version}
61 |
62 |
63 | junit
64 | junit
65 | ${junit.version}
66 | test
67 |
68 |
69 |
70 | org.junit.jupiter
71 | junit-jupiter-api
72 | ${junit.jupiter.version}
73 | test
74 |
75 |
76 | org.springframework.boot
77 | spring-boot-starter-web
78 | ${springboot.version}
79 |
80 |
81 | org.springframework.boot
82 | spring-boot-starter-logging
83 |
84 |
85 |
86 |
87 | io.spring.gradle
88 | dependency-management-plugin
89 | 0.5.3.RELEASE
90 |
91 |
92 | fr.inria.lille.shexjava
93 | shexjava-core
94 | ${shexjava.version}
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | org.jetbrains.kotlin
103 | kotlin-maven-plugin
104 | ${kotlin.version}
105 |
106 |
107 | compile
108 | compile
109 |
110 | compile
111 |
112 |
113 | ${project.basedir}/src/main
114 | ${project.build.outputDirectory}
115 |
116 |
117 |
118 | test-compile
119 | test-compile
120 |
121 | test-compile
122 |
123 |
124 |
125 |
126 |
127 |
128 | org.springframework.boot
129 | spring-boot-maven-plugin
130 |
131 | api.ApplicationKt
132 |
133 | ${springboot.version}
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/mimir/src/main/api/owl/ReasonResponse.kt:
--------------------------------------------------------------------------------
1 | package api.owl
2 |
3 | import api.ReasonerConfig
4 | import dot.colorTemplate.ReasonerNodeColor
5 | import loadModel
6 | import org.apache.jena.rdf.model.Model
7 | import org.apache.jena.riot.RDFFormat
8 | import org.apache.jena.riot.system.PrefixMapFactory
9 | import org.springframework.http.HttpHeaders
10 | import org.springframework.http.HttpHeaders.CONTENT_TYPE
11 | import org.springframework.http.HttpStatus
12 | import org.springframework.http.MediaType
13 | import org.springframework.http.MediaType.TEXT_PLAIN_VALUE
14 | import org.springframework.http.ResponseEntity
15 | import org.springframework.web.bind.annotation.PostMapping
16 | import org.springframework.web.bind.annotation.RequestBody
17 | import org.springframework.web.bind.annotation.RestController
18 | import reasoner.OwlRLWrapper
19 | import toAlternateColoursDOT
20 | import toDOT
21 | import writeTo
22 |
23 | data class ReasonRequest(
24 | val data: String = "",
25 | val data_lang: String = "TTL",
26 | val profile: String = ReasonerConfig.DEFAULT_PROFILE
27 | )
28 | data class ReasonResponse(
29 | val data: String = "",
30 | val error: String = "",
31 | val data_dot: String = ""
32 | )
33 |
34 | @RestController
35 | class ReasonController {
36 |
37 | @PostMapping(
38 | "/api/owl/reason",
39 | consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE],
40 | produces = [MediaType.APPLICATION_JSON_UTF8_VALUE, TEXT_PLAIN_VALUE]
41 | )
42 | fun reason(
43 | @RequestBody requestBody: ReasonRequest
44 | ): ResponseEntity {
45 | val header = HttpHeaders()
46 | if (requestBody.data.isBlank()) return ResponseEntity(ReasonResponse(),HttpStatus.NO_CONTENT)
47 |
48 | var data: String = requestBody.data
49 | val reasoner = OwlRLWrapper()
50 |
51 | try {
52 | // convert to TTL if not TTL
53 | if (requestBody.data_lang != "TTL")
54 | data = loadModel(data, requestBody.data_lang).writeTo(RDFFormat.TTL)
55 |
56 | // Call reasoner and get the result
57 | val (inferred, error) = reasoner.infer(data = data, profile = requestBody.profile)
58 | var dot: String = ""
59 |
60 | // try to convert to DOT (fails when there is literals, because it owlrl uses them as subjects)
61 | dot = try {
62 | loadModel(inferred, "TTL").toDOT()
63 | } catch (e: Exception) {
64 | println("Error reasoning, DOT creation failed: \n reason: ${e.message}")
65 | // display an empty DOT
66 | "digraph G{\n charset=\"utf-8\";\n \n // Edges\n \n // Nodes\n}\n"
67 | }
68 |
69 | // try to get a DOT of the original model and one of the difference
70 | // between original and inferred
71 | val dataModel: Model = loadModel(data, requestBody.data_lang)
72 | val dataDot: String = dataModel.toDOT()
73 | // exclude elements that are in the original model
74 | val diffModel: Model = loadModel(inferred, "TTL").difference(dataModel)
75 | // convert to a differently coloured DOT
76 | val diffDOT = diffModel.toAlternateColoursDOT(
77 | ReasonerNodeColor,
78 | prefixMap = PrefixMapFactory.create(dataModel.nsPrefixMap)
79 | )
80 |
81 | // Mix this DOT strings to display them with different pallets
82 | val mixDOT: String = deleteRepeatedNodes(original = dataDot, other = diffDOT)
83 |
84 | dot = mixDOT
85 |
86 | header.add(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
87 | return ResponseEntity(ReasonResponse(inferred, error, dot), header, HttpStatus.OK)
88 |
89 | } catch (e: Exception) {
90 | println("Error while reasoning, aborting with Error: ${e.message}")
91 | header.add(CONTENT_TYPE, TEXT_PLAIN_VALUE)
92 | return ResponseEntity("Internal Server Error", header, HttpStatus.INTERNAL_SERVER_ERROR)
93 | }
94 | }
95 | }
96 |
97 | fun deleteRepeatedNodes(original: String, other: String): String {
98 | val originLines: List = original.reader().readLines()
99 | val otherLines: List = other.reader().readLines()
100 |
101 | // final Nodes and Edges
102 | val nodes = mutableListOf()
103 | val edges = mutableListOf()
104 |
105 | val nodeRegex: Regex = """"[-a-zA-Z0-9+&@#/%?=~_|!:,.; ]+" \[""".toRegex()
106 |
107 | // Clean lines
108 | originLines.forEach { line: String ->
109 | // process this lines before the __other__ ones
110 | when {
111 | line.isBlank() -> {} // do nothing
112 | line.trim().contains(" -> ") -> edges.add(line.trim())
113 | nodeRegex.containsMatchIn(line.trim()) -> nodes.add(line.trim())
114 | }
115 | }
116 |
117 | // Add only the nodes that are not on the original, and all the edges
118 | otherLines.forEach { line: String ->
119 | when {
120 | line.isBlank() -> {}
121 | line.trim().contains(" -> ") -> edges.add(line.trim())
122 | nodeRegex.containsMatchIn(line.trim()) -> {
123 | // FIXME: un-hardcode
124 | // temp Line is hardcoded to not include the color
125 | val tempLine: String = line.substring(0, line.length - 7).trim()
126 | // see if exist already, add it if it doesn't
127 | if (nodes.none { nodeLine -> nodeLine.startsWith(tempLine) }) {
128 | nodes.add(line.trim())
129 | }
130 | }
131 | }
132 | }
133 |
134 | // build DOT document
135 | return """
136 | digraph G{
137 |
138 | charset="utf-8";
139 |
140 | // Edges
141 | ${(edges.map { it }).joinToString(separator = "\n\t")}
142 |
143 | // Nodes
144 | ${(nodes.map { it }).joinToString(separator = "\n\t")}
145 |
146 | }
147 | """.trimIndent()
148 | }
149 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Configuration file for the Sphinx documentation builder.
4 | #
5 | # This file does only contain a selection of the most common options. For a
6 | # full list see the documentation:
7 | # http://www.sphinx-doc.org/en/master/config
8 |
9 | # -- Path setup --------------------------------------------------------------
10 |
11 | # If extensions (or modules to document with autodoc) are in another directory,
12 | # add these directories to sys.path here. If the directory is relative to the
13 | # documentation root, use os.path.abspath to make it absolute, like shown here.
14 | #
15 | import os
16 | import sys
17 | sys.path.insert(0, os.path.abspath('../..'))
18 |
19 |
20 | # -- Project information -----------------------------------------------------
21 |
22 | project = 'OWL-RL'
23 | copyright = '2020, RDFlib developers'
24 | author = 'RDFlib developers'
25 |
26 | # The short X.Y version
27 | version = ''
28 | # The full version, including alpha/beta/rc tags
29 | release = '5.2.1'
30 |
31 |
32 | # -- General configuration ---------------------------------------------------
33 |
34 | # If your documentation needs a minimal Sphinx version, state it here.
35 | #
36 | # needs_sphinx = '1.0'
37 |
38 | # Add any Sphinx extension module names here, as strings. They can be
39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
40 | # ones.
41 | extensions = [
42 | 'sphinx.ext.autodoc',
43 | 'sphinx.ext.intersphinx',
44 | 'sphinx.ext.viewcode',
45 | 'sphinx.ext.autosummary'
46 | ]
47 |
48 | # generate classes and add to the toctree. See owlrl.rst for example usage.
49 | # autodoc_default_flags = ['members']
50 | autosummary_generate = True
51 |
52 | # Add any paths that contain templates here, relative to this directory.
53 | templates_path = ['_templates']
54 |
55 | # The suffix(es) of source filenames.
56 | # You can specify multiple suffix as a list of string:
57 | #
58 | # source_suffix = ['.rst', '.md']
59 | source_suffix = '.rst'
60 |
61 | # The master toctree document.
62 | master_doc = 'index'
63 |
64 | # The language for content autogenerated by Sphinx. Refer to documentation
65 | # for a list of supported languages.
66 | #
67 | # This is also used if you do content translation via gettext catalogs.
68 | # Usually you set "language" from the command line for these cases.
69 | language = None
70 |
71 | # List of patterns, relative to source directory, that match files and
72 | # directories to ignore when looking for source files.
73 | # This pattern also affects html_static_path and html_extra_path.
74 | exclude_patterns = []
75 |
76 | # The name of the Pygments (syntax highlighting) style to use.
77 | pygments_style = None
78 |
79 |
80 | # -- Options for HTML output -------------------------------------------------
81 |
82 | # The theme to use for HTML and HTML Help pages. See the documentation for
83 | # a list of builtin themes.
84 | #
85 | html_theme = 'sphinx_rtd_theme'
86 |
87 | # Theme options are theme-specific and customize the look and feel of a theme
88 | # further. For a list of options available for each theme, see the
89 | # documentation.
90 | #
91 | # html_theme_options = {}
92 |
93 | # Add any paths that contain custom static files (such as style sheets) here,
94 | # relative to this directory. They are copied after the builtin static files,
95 | # so a file named "default.css" will overwrite the builtin "default.css".
96 | html_static_path = ['_static']
97 |
98 | # Custom sidebar templates, must be a dictionary that maps document names
99 | # to template names.
100 | #
101 | # The default sidebars (for documents that don't match any pattern) are
102 | # defined by theme itself. Builtin themes are using these templates by
103 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
104 | # 'searchbox.html']``.
105 | #
106 | # html_sidebars = {}
107 |
108 | html_logo = "../../OWL-RL.png"
109 |
110 |
111 | # -- Options for HTMLHelp output ---------------------------------------------
112 |
113 | # Output file base name for HTML help builder.
114 | htmlhelp_basename = 'OWL-RLdoc'
115 |
116 |
117 | # -- Options for LaTeX output ------------------------------------------------
118 |
119 | latex_elements = {
120 | # The paper size ('letterpaper' or 'a4paper').
121 | #
122 | # 'papersize': 'letterpaper',
123 |
124 | # The font size ('10pt', '11pt' or '12pt').
125 | #
126 | # 'pointsize': '10pt',
127 |
128 | # Additional stuff for the LaTeX preamble.
129 | #
130 | # 'preamble': '',
131 |
132 | # Latex figure (float) alignment
133 | #
134 | # 'figure_align': 'htbp',
135 | }
136 |
137 | # Grouping the document tree into LaTeX files. List of tuples
138 | # (source start file, target name, title,
139 | # author, documentclass [howto, manual, or own class]).
140 | latex_documents = [
141 | (master_doc, 'OWL-RL.tex', 'OWL-RL Documentation',
142 | 'CSIRO Land and Water', 'manual'),
143 | ]
144 |
145 |
146 | # -- Options for manual page output ------------------------------------------
147 |
148 | # One entry per manual page. List of tuples
149 | # (source start file, name, description, authors, manual section).
150 | man_pages = [
151 | (master_doc, 'owl-rl', 'OWL-RL Documentation',
152 | [author], 1)
153 | ]
154 |
155 |
156 | # -- Options for Texinfo output ----------------------------------------------
157 |
158 | # Grouping the document tree into Texinfo files. List of tuples
159 | # (source start file, target name, title, author,
160 | # dir menu entry, description, category)
161 | texinfo_documents = [
162 | (master_doc, 'OWL-RL', 'OWL-RL Documentation',
163 | author, 'OWL-RL', 'One line description of project.',
164 | 'Miscellaneous'),
165 | ]
166 |
167 |
168 | # -- Options for Epub output -------------------------------------------------
169 |
170 | # Bibliographic Dublin Core info.
171 | epub_title = project
172 |
173 | # The unique identifier of the text. This can be a ISBN number
174 | # or the project homepage.
175 | #
176 | # epub_identifier = ''
177 |
178 | # A unique identification for the text.
179 | #
180 | # epub_uid = ''
181 |
182 | # A list of files that should not be packed into the epub file.
183 | epub_exclude_files = ['search.html']
184 |
185 |
186 | # -- Extension configuration -------------------------------------------------
187 |
188 | # -- Options for intersphinx extension ---------------------------------------
189 |
190 | # Example configuration for intersphinx: refer to the Python standard library.
191 | intersphinx_mapping = {'https://docs.python.org/': None}
--------------------------------------------------------------------------------
/mimir/src/main/dot/DOTShell.kt:
--------------------------------------------------------------------------------
1 | package dot
2 |
3 | import dot.colorTemplate.NodeColor
4 | import org.apache.jena.atlas.io.IndentedWriter
5 | import org.apache.jena.graph.Graph
6 | import org.apache.jena.graph.Node
7 | import org.apache.jena.graph.Triple
8 | import org.apache.jena.riot.other.GLib
9 | import org.apache.jena.riot.system.PrefixMap
10 | import org.apache.jena.riot.system.PrefixMapFactory
11 | import org.apache.jena.sparql.util.Context
12 |
13 | open class DOTShell(
14 | protected var out: IndentedWriter,
15 | protected var prefixMap: PrefixMap = PrefixMapFactory.emptyPrefixMap(),
16 | protected var baseURI: String?,
17 | protected var context: Context?
18 | ) {
19 | private var graph: Graph = Graph.emptyGraph
20 |
21 | private fun writeGraphStart() {
22 | // Prints the start of the graph, and places new lines for readability
23 | out.print("digraph G{\n")
24 | }
25 |
26 | private fun writeGraphEnd() {
27 | // Prints end of graph, ending with empty line
28 | out.println("}")
29 | }
30 |
31 | fun writeGraphDOT(graph: Graph, colors: NodeColoring = NodeColor) {
32 | this.graph = graph
33 | // Writes graph on DOT syntax
34 | writeGraphStart()
35 | out.incIndent()
36 | out.println("charset=\"utf-8\";")
37 | out.println()
38 |
39 | // Get every Triple on the Graph
40 | val tripleIterator: Iterator = graph.find(Node.ANY, Node.ANY, Node.ANY)
41 | // Get Nodes
42 | val nodesIterator: Iterator = listSubjectsAndObjects()
43 |
44 | out.println("// Edges")
45 | tripleIterator.forEach { triple: Triple ->
46 | // Prints a row for each Edge
47 | run {
48 | when {
49 | triple.`object`.isLiteral ->
50 | out.println(
51 | "\"${ triple.subject }\" -> \"${ prettyTriple(triple) }\" " +
52 | "[label=\"${ prettyLabel(triple.predicate) }\",color=\"${colors.literalEdge}\"]"
53 | )
54 | else ->
55 | out.println(
56 | "\"${ triple.subject }\" -> \"${ triple.`object` }\" " +
57 | "[label=\"${ prettyLabel(triple.predicate) }\",color=\"${colors.normalEdge}\"]"
58 | )
59 | }
60 | }
61 | }
62 | out.println()
63 |
64 | out.println("// Nodes")
65 | nodesIterator.forEach { node: Node ->
66 | run {
67 | when {
68 | // Write a row for each node
69 | node.isURI ->
70 | out.println(
71 | "\"${ node.uri }\" [label=\"${ prettyLabel(node) }\",shape=ellipse,color=\"${colors.uri}\"]"
72 | )
73 | node.isBlank ->
74 | out.println(
75 | "\"${node.blankNodeLabel}\" [label=\"\",shape=circle,color=\"${colors.blank}\"]"
76 | )
77 | node.isLiteral ->
78 | when {
79 | node.literal.value.toString().isNotEmpty() ->
80 | out.println(
81 | "\"${prettyNode(node)}\" [label=\"${prettyLiteralLabel(node)}\"," +
82 | "shape=record,color=\"${colors.literal}\",${langLiteral(node)}" +
83 | "${dataTypeLiteral(node)}]"
84 | )
85 | }
86 | }
87 | }
88 | }
89 |
90 | out.decIndent()
91 | writeGraphEnd()
92 | }
93 |
94 | // Graph writing functions
95 | private fun listSubjects(): Iterator {
96 | return GLib.listSubjects(graph)
97 | }
98 |
99 | private fun listObjects(): Iterator {
100 | return GLib.listObjects(graph)
101 | }
102 |
103 | private fun listSubjectsAndObjects(): Iterator {
104 | val subjectsIterator: Iterator = listSubjects()
105 | val objectsIterator: Iterator = listObjects()
106 |
107 | val nodes = mutableListOf()
108 | // add all elements to a list
109 | subjectsIterator.forEach { aNode: Node -> nodes.add(aNode) }
110 | objectsIterator.forEach { aNode: Node -> nodes.add(aNode) }
111 |
112 | val filteredNodes = nodes.distinct()
113 |
114 | return filteredNodes.iterator()
115 | }
116 |
117 | private fun prettyLabel(node: Node): String {
118 | return when (node.prefix(prefixMap)) {
119 | null -> node.uri
120 | else -> "${node.prefix(prefixMap)}:${nodeLocalName(node)}"
121 | }
122 | }
123 |
124 | private fun nodeLocalName(node: Node): String {
125 | return node.getURI().substring(Math.max(node.getURI().lastIndexOf('/'),node.getURI().lastIndexOf('#'))+1)
126 | }
127 |
128 | private fun prettyTriple(triple: Triple): String {
129 | return when (triple.`object`.literalLanguage) {
130 | "" -> triple.`object`.literal.lexicalForm.toString().replace("\"", "\'")
131 | else -> triple.`object`.literal.lexicalForm.toString().replace("\"", "\'") +
132 | "@" + triple.`object`.literalLanguage
133 | }
134 | }
135 |
136 | private fun prettyNode(node: Node): String {
137 | return when (node.literalLanguage) {
138 | "" -> node.literal.lexicalForm.toString().replace("\"", "\'")
139 | else -> node.literal.lexicalForm.toString().replace("\"", "\'") +
140 | "@" + node.literalLanguage
141 | }
142 | }
143 |
144 | private fun prettyLiteralLabel(node: Node): String {
145 | return node.literal.lexicalForm.toString().replace("\"", "\'")
146 | }
147 |
148 | private fun langLiteral(node: Node): String {
149 | return when (node.literalLanguage) {
150 | "" -> ""
151 | else -> "lang= \"${node.literalLanguage}\","
152 | }
153 | }
154 |
155 | private fun dataTypeLiteral(node: Node): String {
156 | return "datatype= \"${node.literalDatatypeURI}\""
157 | }
158 |
159 | }
160 |
161 | // Auxiliary function that obtains a prefix for a given Node, must be URI
162 | private fun Node.prefix(prefixMap: PrefixMap): String? {
163 | return when (prefixMap.abbrev(this.nameSpace)) {
164 | null -> null
165 | else -> prefixMap.abbrev(this.nameSpace).left
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/Doc_OLD/module-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | Module Hierarchy
7 |
8 |
9 |
10 |
11 |
13 |
14 |
16 |
17 |
18 | Home
20 |
21 |
22 | Trees
24 |
25 |
26 | Indices
28 |
29 |
30 | Help
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
53 | [ Module Hierarchy
54 | | Class Hierarchy ]
55 |
56 | Module Hierarchy
57 |
58 | RDFClosure : This module is brute force implementation of the 'finite' version
59 | of RDFS
60 | semantics and of OWL 2 RL on the top of RDFLib (with some caveats,
63 | see below).
64 |
84 |
85 |
86 |
87 |
89 |
90 |
91 | Home
93 |
94 |
95 | Trees
97 |
98 |
99 | Indices
101 |
102 |
103 | Help
105 |
106 |
107 |
108 |
109 |
110 |
111 |
114 |
118 |
119 |
120 |
121 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/mimir/src/main/shex/ShexWrapper.kt:
--------------------------------------------------------------------------------
1 | package shex
2 |
3 | import api.ShexConfig
4 | import fr.inria.lille.shexjava.GlobalFactory
5 | import fr.inria.lille.shexjava.schema.Label
6 | import fr.inria.lille.shexjava.schema.ShexSchema
7 | import fr.inria.lille.shexjava.schema.parsing.GenParser
8 | import fr.inria.lille.shexjava.validation.ValidationAlgorithm
9 | import isAbbreviatedIRI
10 | import loadModel
11 | import org.apache.commons.rdf.api.Graph
12 | import org.apache.commons.rdf.api.IRI
13 | import org.apache.commons.rdf.rdf4j.RDF4J
14 | import org.apache.jena.atlas.io.IndentedWriter
15 | import org.apache.jena.riot.system.PrefixMap
16 | import org.apache.jena.riot.system.PrefixMapFactory
17 | import org.eclipse.rdf4j.rio.RDFFormat
18 | import org.eclipse.rdf4j.rio.Rio
19 | import writeTo
20 | import java.io.ByteArrayOutputStream
21 | import java.io.File
22 | import java.nio.file.Paths
23 |
24 | class ShexWrapper(private val factory: RDF4J = RDF4J()) {
25 | private val modelPrefixMap: PrefixMap = PrefixMapFactory.create()
26 | private val shapePrefixMap: PrefixMap = PrefixMapFactory.create()
27 |
28 | init {
29 | GlobalFactory.RDFFactory = factory // set global factory for ShexJava
30 | }
31 |
32 | fun createDataGraph(data: String, lang: String): Graph {
33 | // Convert Data to Turtle (on Jena)
34 | val dataModel = loadModel(data, lang)
35 | val dataOnTTL: String = dataModel.writeTo(org.apache.jena.riot.RDFFormat.TTL)
36 |
37 | val baseIRI = "http://example.org/"
38 |
39 | // use RDF4J with eclipse to create apache.commons.rdf.api.Graph
40 | val eclipseModel: org.eclipse.rdf4j.model.Model = Rio.parse(
41 | dataOnTTL.reader(),
42 | baseIRI,
43 | RDFFormat.TURTLE
44 | )
45 |
46 | // generate data model prefixMap
47 | modelPrefixMap.putAll(dataModel.nsPrefixMap)
48 |
49 | // Get a graph from the data
50 | return factory.asGraph(eclipseModel)
51 | }
52 |
53 | fun createSchema(shape: String): ShexSchema {
54 | // Load schema to shex java
55 | val tempDirectory = Paths.get(ShexConfig.TMP_DIR_NAME).toFile()
56 | val tempShexFile: File = createTempFile(
57 | ShexConfig.TMP_NAME_PREFIX,
58 | ShexConfig.TMP_NAME_SUFFIX,
59 | tempDirectory
60 | )
61 | tempShexFile.writeText(shape, Charsets.UTF_8)
62 |
63 | // create custom prefixMapping from Schema
64 | generatePrefixMap(shapePrefixMap, tempShexFile)
65 |
66 | val schema: ShexSchema = GenParser.parseSchema(factory, tempShexFile.toPath())
67 | tempShexFile.delete()
68 | return schema
69 | }
70 |
71 | private fun generatePrefixMap(prefixMap: PrefixMap, file: File) {
72 | // look for prefixes to create our map
73 | val regex = Regex("^prefix\\s+[a-zA-Z]*:\\s+<(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]>|PREFIX\\s+[a-zA-Z]*:\\s+<(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]>")
74 | file.forEachLine {
75 | when {
76 | it.contains(regex) -> {
77 | var prefixString = it.trim()
78 | // get prefix abbreviation
79 | prefixString = prefixString.removePrefix("prefix ").removePrefix("PREFIX ").trimStart()
80 | val abbreviation = prefixString.substringBefore(':') + ':'
81 | val extended = prefixString.substringAfter('<').substringBefore('>')
82 | prefixMap.add(abbreviation, extended)
83 | }
84 | }
85 | }
86 | }
87 |
88 | fun parseMap(shapeMap: String): List {
89 | val mappingList: MutableList = mutableListOf()
90 |
91 | // format map
92 | shapeMap.trim()
93 | shapeMap.replace("\n\r ".toRegex(), "") // delete line breaks betweeen statements
94 |
95 | // convert to List
96 | val elements = shapeMap.split(",", ";")
97 | elements.forEach { element ->
98 | run {
99 | if (!element.contains('@')) {
100 | throw Exception("Bad Mapping Syntax: missing @, use nodeLabel@shapeLabel syntax")
101 | } else {
102 | val pair = element.split('@')
103 | if (pair.size != 2) {
104 | throw Exception("Bad Mapping Syntax: missing element on mapping")
105 | } else {
106 | // shex java uses exclusively expanded IRIs, so here we create expanded
107 | // versions for any mapping and save the user input to be printed later
108 |
109 | // Node label processing
110 | val nodeLabel = pair[0].trim()
111 | var expandedNodeLabel = nodeLabel.trim('<').trim('>')
112 | // expand node IRI for shex java
113 | if (pair[0].trim().isAbbreviatedIRI()) expandedNodeLabel = modelPrefixMap.expand(nodeLabel)
114 | val node: IRI = factory.createIRI(expandedNodeLabel)
115 |
116 | // Shape label processing
117 | val shapeLabel = pair[1].trim('<').trim('>')
118 | var expandedShapeLabel = shapeLabel
119 | if (shapeLabel.isAbbreviatedIRI()) expandedShapeLabel = shapePrefixMap.expand(shapeLabel)
120 | val shape: Label = Label(factory.createIRI(expandedShapeLabel))
121 |
122 | // save to mapping object
123 | mappingList.add(
124 | ShexShapeMap(
125 | node, // RDF term
126 | shape, // shape label
127 | pair[0].trim(), // original node as given
128 | pair[1].trim() // original shape as given
129 | ) // save original terms
130 | )
131 | }
132 | }
133 | }
134 | }
135 | return mappingList.toList()
136 | }
137 |
138 | fun validateMapping(validationAlgorithm: ValidationAlgorithm, shapeMapping: List): String {
139 | val baos = ByteArrayOutputStream()
140 | val writer: IndentedWriter = IndentedWriter(baos)
141 | writer.println("ShEx Validation Report:")
142 | writer.incIndent() // adds an indentation to each line
143 |
144 | shapeMapping.forEach { mapping: ShexShapeMap ->
145 | // Validate pair
146 | validationAlgorithm.validate(mapping.nodeLabel, mapping.shapeLabel)
147 |
148 | // Print results for each pair
149 | when (validationAlgorithm.typing.isConformant(mapping.nodeLabel, mapping.shapeLabel)) {
150 | true ->
151 | writer.println("✅ ${mapping.originalNode} conforms with ${mapping.originalShape}")
152 | false ->
153 | writer.println("❌ ${mapping.originalNode} does not conform with ${mapping.originalShape}")
154 | }
155 | }
156 | writer.flush()
157 | return baos.toString()
158 | }
159 | }
--------------------------------------------------------------------------------
/mimir/src/main/Utils.kt:
--------------------------------------------------------------------------------
1 | import org.apache.jena.query.ResultSet
2 | import org.apache.jena.query.ResultSetFormatter.*
3 | import org.apache.jena.rdf.model.Model
4 | import org.apache.jena.rdf.model.ModelFactory
5 | import org.apache.jena.riot.Lang
6 | import org.apache.jena.riot.RDFDataMgr
7 | import org.apache.jena.riot.RDFFormat
8 | import org.apache.jena.sparql.sse.SSE
9 | import java.io.ByteArrayInputStream
10 | import java.io.ByteArrayOutputStream
11 | import java.lang.Exception
12 | import kotlin.text.contains
13 |
14 | import dot.DOTLang
15 | import dot.DOTShell
16 | import dot.NodeColoring
17 | import org.apache.commons.rdf.api.Graph
18 | import org.apache.jena.atlas.io.IndentedWriter
19 | import org.apache.jena.query.Dataset
20 | import org.apache.jena.rdf.model.ResourceFactory
21 | import org.apache.jena.riot.system.PrefixMap
22 | import org.apache.jena.riot.system.PrefixMapBase
23 | import org.apache.jena.riot.system.PrefixMapFactory
24 | import org.apache.jena.riot.system.PrefixMapWrapper
25 | import org.apache.jena.shacl.ValidationReport
26 | import org.apache.jena.shacl.lib.ShLib
27 | import org.apache.jena.sparql.util.Context
28 |
29 | fun loadModel(data: String, lang: String): Model {
30 | // Load data on to a model and returns the model
31 | val model = ModelFactory.createDefaultModel()
32 | val inputStream = ByteArrayInputStream(data.toByteArray(Charsets.UTF_8))
33 | try {
34 | model.read(inputStream, null, lang)
35 | } catch (e: Exception) {
36 | throw e
37 | }
38 | return model
39 | }
40 |
41 | fun Model.writeTo(lang: RDFFormat): String {
42 | // Writes to specified Lang
43 | val baos = ByteArrayOutputStream()
44 | try {
45 | RDFDataMgr.write(baos, this, lang)
46 | } catch (e: Exception) {
47 | throw e
48 | }
49 | return baos.toString()
50 | }
51 |
52 | fun Model.toDOT(): String {
53 | return this.writeTo(RDFFormat(DOTLang))
54 | }
55 |
56 | fun Model.toAlternateColoursDOT(colors: NodeColoring, prefixMap: PrefixMap = PrefixMapFactory.create(this.nsPrefixMap)): String {
57 | // Uses the internal DOT Writer added to Jena, with a different
58 | // set of colors for the nodes
59 | val graph = this.graph
60 | val baos = ByteArrayOutputStream()
61 | val indWriter = IndentedWriter(baos)
62 | val shell = DOTShell(indWriter, prefixMap, baseURI = "rdfplayground.dcc.uchile.cl", context = Context.emptyContext)
63 | shell.writeGraphDOT(graph, colors)
64 |
65 | indWriter.flush()
66 | return baos.toString()
67 | }
68 |
69 | fun ResultSet.formatAs(format: String): String {
70 | val set: ResultSet = this
71 | val outStream = ByteArrayOutputStream()
72 | // Write to ByteArray stream using ResultSetFormatter and return as String
73 | when (format) {
74 | "Text" -> out(outStream, set)
75 | "XML" -> outputAsXML(outStream, set)
76 | "SSE" -> outputAsSSE(outStream, set)
77 | "CSV" -> outputAsCSV(outStream, set)
78 | "JSON" -> outputAsJSON(outStream, set)
79 | "TSV" -> outputAsTSV(outStream, set)
80 | "TTL" -> output(outStream, set, Lang.TURTLE)
81 | else -> throw Exception("Unsupported language")
82 | }
83 | return outStream.toString()
84 | }
85 |
86 | fun Boolean.formatAskAs(format: String): String {
87 | val bool: Boolean = this
88 | val outStream = ByteArrayOutputStream()
89 | // Write Ask response to ByteArray stream using ResultSetFormatter and return as String
90 | when (format) {
91 | "Text" -> out(outStream, bool)
92 | "XML" -> outputAsXML(outStream, bool)
93 | "SSE" -> outputAsSSE(outStream, bool)
94 | "CSV" -> outputAsCSV(outStream, bool)
95 | "JSON" -> outputAsJSON(outStream, bool)
96 | "TSV" -> outputAsTSV(outStream, bool)
97 | "TTL" -> output(outStream, bool, Lang.TURTLE)
98 | else -> throw Exception("Unsupported language")
99 | }
100 | return outStream.toString()
101 | }
102 |
103 | fun Model.formatAs(format: String): Pair {
104 | val outStream = ByteArrayOutputStream()
105 | var outFormat = "TTL"
106 | // Write Ask response to ByteArray stream using ResultSetFormatter and return as String
107 | when (format) {
108 | "Text" -> RDFDataMgr.write(outStream, this, Lang.TTL)
109 | "XML" -> {
110 | RDFDataMgr.write(outStream, this, Lang.RDFXML)
111 | outFormat = "XML"
112 | }
113 | "SSE" -> {
114 | SSE.write(outStream, this)
115 | outFormat = "SSE"
116 | }
117 | "CSV" -> {
118 | RDFDataMgr.write(outStream, this, Lang.CSV)
119 | outFormat = "CSV"
120 | }
121 | "JSON" -> {
122 | RDFDataMgr.write(outStream, this, Lang.RDFJSON)
123 | outFormat = "JSON"
124 | }
125 | "TSV" -> {
126 | RDFDataMgr.write(outStream, this, Lang.TSV)
127 | outFormat = "TSV"
128 | }
129 | "TTL" -> RDFDataMgr.write(outStream, this, Lang.TURTLE)
130 | "NTRIPLES" -> RDFDataMgr.write(outStream, this, Lang.NTRIPLES)
131 | "DOT" -> RDFDataMgr.write(outStream, this, DOTLang)
132 | else -> throw Exception("Unsupported language")
133 | }
134 | return Pair(outStream.toString(), outFormat)
135 | }
136 |
137 | fun parseFormat(acceptHeader: String): MutableList {
138 | val list: MutableList = mutableListOf()
139 | val accept: List = acceptHeader.split(',', ignoreCase = true)
140 | accept.forEach {
141 | when {
142 | it.contains(MimeType.text, ignoreCase = true) -> list.add("Text")
143 | it.contains(MimeType.xml, ignoreCase = true) -> list.add("XML")
144 | it.contains(MimeType.sse, ignoreCase = true) -> list.add("SSE")
145 | it.contains(MimeType.csv, ignoreCase = true) -> list.add("CSV")
146 | it.contains(MimeType.json, ignoreCase = true) -> list.add("JSON")
147 | it.contains(MimeType.tsv, ignoreCase = true) -> list.add("TSV")
148 | it.contains(MimeType.ttl, ignoreCase = true) -> list.add("TTL")
149 | it.contains(MimeType.ntriples, ignoreCase = true) -> list.add("NTRIPLES")
150 | it.contains(MimeType.dot, ignoreCase = true) -> list.add("DOT")
151 | else -> println("Formato no reconocido")
152 | }
153 | }
154 | return list
155 | }
156 |
157 | object MimeType {
158 | const val text = "text/plain ;charset=utf-8"
159 | const val xml = "application/xml ;charset=utf-8"
160 | const val sse = "text/x-sse ;charset=utf-8"
161 | const val csv = "text/csv ;charset=utf-8"
162 | const val json = "application/json ;charset=utf-8"
163 | const val tsv = "text/tab-separated-values ;charset=utf-8"
164 | const val ttl = "text/turtle ;charset=utf-8"
165 | const val ntriples = "application/n-triples ;charset=utf-8"
166 | const val dot = "text/vnd.graphviz ;charset=utf-8"
167 | }
168 |
169 | fun toMimeType(type: String): String {
170 | return when (type) {
171 | "Text" -> MimeType.text
172 | "XML" -> MimeType.xml
173 | "SSE" -> MimeType.sse
174 | "CSV" -> MimeType.csv
175 | "JSON" -> MimeType.json
176 | "TSV" -> MimeType.tsv
177 | "TTL" -> MimeType.ttl
178 | "NTRIPLES" -> MimeType.ntriples
179 | "DOT" -> MimeType.dot
180 | else -> ""
181 | }
182 | }
183 |
184 | fun ValidationReport.toPrintableString(): String {
185 | val outStream = ByteArrayOutputStream()
186 | ShLib.printReport(outStream, this)
187 |
188 | return outStream.toString()
189 | }
190 |
191 | fun String.isAbbreviatedIRI(): Boolean {
192 | return this.contains(Regex("^[_a-zA-Z]*:[a-zA-Z]+"))
193 | }
194 |
--------------------------------------------------------------------------------
/mimir/src/main/reasoner/owlrl/owlrl/CombinedClosure.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | """
4 | The combined closure: performing *both* the OWL 2 RL and RDFS closures.
5 |
6 | The two are very close but there are some rules in RDFS that are not in OWL 2 RL (eg, the axiomatic
7 | triples concerning the container membership properties). Using this closure class the
8 | OWL 2 RL implementation becomes a full extension of RDFS.
9 |
10 | **Requires**: `RDFLib`_, 4.0.0 and higher.
11 |
12 | .. _RDFLib: https://github.com/RDFLib/rdflib
13 |
14 | **License**: This software is available for use under the `W3C Software License`_.
15 |
16 | .. _W3C Software License: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
17 |
18 | **Organization**: `World Wide Web Consortium`_
19 |
20 | .. _World Wide Web Consortium: http://www.w3.org
21 |
22 | **Author**: `Ivan Herman`_
23 |
24 | .. _Ivan Herman: http://www.w3.org/People/Ivan/
25 |
26 | """
27 |
28 | __author__ = 'Ivan Herman'
29 | __contact__ = 'Ivan Herman, ivan@w3.org'
30 | __license__ = 'W3C® SOFTWARE NOTICE AND LICENSE, http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231'
31 |
32 | from owlrl.RDFS import Resource, Class, Datatype
33 | from owlrl.OWL import OWLClass, Thing, equivalentClass, DataRange
34 |
35 | from owlrl.RDFSClosure import RDFS_Semantics
36 | from owlrl.OWLRL import OWLRL_Semantics
37 |
38 | ######################################################################################################
39 |
40 |
41 | # noinspection PyPep8Naming
42 | class RDFS_OWLRL_Semantics(RDFS_Semantics, OWLRL_Semantics):
43 | """
44 | Common subclass of the RDFS and OWL 2 RL semantic classes. All methods simply call back
45 | to the functions in the superclasses. This may lead to some unnecessary duplication of terms
46 | and rules, but it it not so bad. Also, the additional identification defined for OWL Full,
47 | ie, Resource being the same as Thing and OWL and RDFS classes being identical are added to the
48 | triple store.
49 |
50 | Note that this class is also a possible user extension point: subclasses can be created that
51 | extend the standard functionality by extending this class. This class *always*} performs RDFS inferences.
52 | Subclasses have to set the :code:`self.rdfs` flag explicitly to the requested value if that is to be controlled.
53 |
54 | :param graph: The RDF graph to be extended.
55 | :type graph: :class:`rdflib.Graph`
56 |
57 | :param axioms: Whether (non-datatype) axiomatic triples should be added or not.
58 | :type axioms: bool
59 |
60 | :param daxioms: Whether datatype axiomatic triples should be added or not.
61 | :type daxioms: bool
62 |
63 | :param rdfs: Placeholder flag (used in subclassed only, it is always defaulted to True in this class)
64 | :type rdfs: bool
65 |
66 | :var full_binding_triples: Additional axiom type triples that are added to the combined semantics; these 'bind'
67 | the RDFS and the OWL worlds together.
68 |
69 | :var rdfs: (bool) Whether RDFS inference is to be performed or not. In this class instance the value is *always*
70 | :code:`True`, subclasses may explicitly change it at initialization time.
71 | :type rdfs: bool
72 | """
73 | full_binding_triples = [
74 | (Thing, equivalentClass, Resource),
75 | (Class, equivalentClass, OWLClass),
76 | (DataRange, equivalentClass, Datatype)
77 | ]
78 |
79 | def __init__(self, graph, axioms, daxioms, rdfs=True):
80 | """
81 | @param graph: the RDF graph to be extended
82 | @type graph: rdflib.Graph
83 | @param axioms: whether (non-datatype) axiomatic triples should be added or not
84 | @type axioms: bool
85 | @param daxioms: whether datatype axiomatic triples should be added or not
86 | @type daxioms: bool
87 | @param rdfs: placeholder flag (used in subclassed only, it is always defaulted to True in this class)
88 | @type rdfs: boolean
89 | """
90 | OWLRL_Semantics.__init__(self, graph, axioms, daxioms, rdfs)
91 | RDFS_Semantics.__init__(self, graph, axioms, daxioms, rdfs)
92 | self.rdfs = True
93 |
94 | # noinspection PyMethodMayBeStatic
95 | @staticmethod
96 | def add_new_datatype(uri, conversion_function, datatype_list, subsumption_dict=None, subsumption_key=None,
97 | subsumption_list=None):
98 | """
99 | If an extension wants to add new datatypes, this method should be invoked at initialization time.
100 |
101 | :param uri: URI for the new datatypes, like owl_ns["Rational"].
102 |
103 | :param conversion_function: A function converting the lexical representation of the datatype to a Python value,
104 | possibly raising an exception in case of unsuitable lexical form.
105 |
106 | :param datatype_list: List of datatypes already in use that has to be checked.
107 | :type datatype_list: list
108 |
109 | :param subsumption_dict: Dictionary of subsumption hierarchies (indexed by the datatype URI-s).
110 | :type subsumption_dict: dict
111 |
112 | :param subsumption_key: Key in the dictionary, if None, the uri parameter is used.
113 | :type subsumption_key: str
114 |
115 | :param subsumption_list: List of subsumptions associated to a subsumption key (ie, all datatypes that are
116 | superclasses of the new datatype).
117 | :type subsumption_list: list
118 | """
119 | from .DatatypeHandling import AltXSDToPYTHON, use_Alt_lexical_conversions
120 |
121 | if datatype_list:
122 | datatype_list.append(uri)
123 |
124 | if subsumption_dict and subsumption_list:
125 | if subsumption_key:
126 | subsumption_dict[subsumption_key] = subsumption_list
127 | else:
128 | subsumption_dict[uri] = subsumption_list
129 |
130 | AltXSDToPYTHON[uri] = conversion_function
131 | use_Alt_lexical_conversions()
132 |
133 | def post_process(self):
134 | """
135 | Do some post-processing step. This method when all processing is done, but before handling possible
136 | errors (I.e., the method can add its own error messages). By default, this method is empty, subclasses
137 | can add content to it by overriding it.
138 | """
139 | OWLRL_Semantics.post_process(self)
140 |
141 | def rules(self, t, cycle_num):
142 | """
143 | :param t: A triple (in the form of a tuple).
144 | :type t: tuple
145 |
146 | :param cycle_num: Which cycle are we in, starting with 1. This value is forwarded to all local rules; it is
147 | also used locally to collect the bnodes in the graph.
148 | :type cycle_num: int
149 | """
150 | OWLRL_Semantics.rules(self, t, cycle_num)
151 | if self.rdfs:
152 | RDFS_Semantics.rules(self, t, cycle_num)
153 |
154 | def add_axioms(self):
155 | if self.rdfs:
156 | RDFS_Semantics.add_axioms(self)
157 | OWLRL_Semantics.add_axioms(self)
158 |
159 | def add_d_axioms(self):
160 | if self.rdfs:
161 | RDFS_Semantics.add_d_axioms(self)
162 | OWLRL_Semantics.add_d_axioms(self)
163 |
164 | def one_time_rules(self):
165 | """Adds some extra axioms and calls for the d_axiom part of the OWL Semantics."""
166 | for t in self.full_binding_triples:
167 | self.store_triple(t)
168 |
169 | # Note that the RL one time rules include the management of datatype which is a true superset
170 | # of the rules in RDFS. It is therefore unnecessary to add those even self.rdfs is True.
171 | OWLRL_Semantics.one_time_rules(self)
172 |
--------------------------------------------------------------------------------