Skip to content

Commit

Permalink
Solves some minor problems related to ShEx and SHACL generation. Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
herminiogg committed Mar 14, 2024
1 parent 13c3ef0 commit 6780ba4
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 4 deletions.
14 changes: 12 additions & 2 deletions src/main/scala/com/herminiogarcia/shexml/shex/SHACLGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,18 @@ class SHACLGenerator(dataset: Dataset, closed: Boolean) {
val shapeName = name.split(':')(1)
val shapeSubject = shapePrefix + shapeName
output.add(createStatement(shapeSubject, rdfPrefix + "type", shPrefix + "NodeShape"))
//Class-based target, could be also implemented searching for rdf:type predicate
output.add(createStatement(shapeSubject, shPrefix + "targetClass", shapeSubject))

val rdfType = predicateObjects
.find(po => po.predicate.prefix == "rdf:" && po.predicate.localname == "type")
.flatMap(_.objectElement match {
case FixedValue(value) =>
val targetClassPrefix = prefixTable(value.split(':')(0) + ":")
val targetClassName = name.split(':')(1)
Some(targetClassPrefix + targetClassName)
case _ => None
})

output.add(createStatement(shapeSubject, shPrefix + "targetClass", rdfType.getOrElse(shapeSubject)))
if(closed) {
output.add(createStatementWithLiteral(shapeSubject, shPrefix + "closed", "true", xsdPrefix + "boolean"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class ShExGeneratorVisitor(inferences: List[ShExMLInferredCardinalitiesAndDataty
override def doVisit(ast: com.herminiogarcia.shexml.ast.AST, optionalArgument: HashMap[String, String]): ShExSubsetAST = ast match {
case ShExML(declarations, graphs, shapes) => {
val prefixes = declarations.filter(_.declarationStatement.isInstanceOf[com.herminiogarcia.shexml.ast.Prefix])
.appended(Prefix(Var("rdf:"), URL("http://www.w3.org/1999/02/22-rdf-syntax-ns#")))
.map(doVisit(_, optionalArgument).asInstanceOf[com.herminiogarcia.shexml.shex.Prefix])
val shexGraphs = graphs.map(doVisit(_, optionalArgument).asInstanceOf[com.herminiogarcia.shexml.shex.Graph])
val shexShapes = shapes.map(doVisit(_, optionalArgument).asInstanceOf[com.herminiogarcia.shexml.shex.Shape])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ class ShExPrinter {
}

case Shape(name, partialFixedValue, predicateObjects) => {
val partialFixedValuePrint = "IRI" //until confirmation this seems not to be working in ShEx -> print(partialFixedValue)
val partialFixedValuePrint =
if(partialFixedValue.start == "_:") "Bnode"
else "IRI" //until confirmation this seems not to be working in ShEx -> print(partialFixedValue)
val predicateObjectsPrint = predicateObjects.map(print(_, indentation + 1)).mkString("\n")
generateIndentation(indentation) + name + " " + partialFixedValuePrint + " {\n" +
predicateObjectsPrint + "\n" + generateIndentation(indentation) + "}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable,
ShapeMapShape(":", splittedShapeName(1))
val node = Node(shapePrefix, normaliseURI(r))
val shapeMap = ShapeMapInference(node, shapeMapShape)
shapeMapTable += shapeMap
if(shapePrefix != "_:") shapeMapTable += shapeMap
})
})
finalActions.map(r => Result(r.id, r.rootIds, r.results.map(ir => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class FilmsTest extends AnyFunSuite with SHACLValidation {
|EXPRESSION films <films_xml_file.film_xml UNION films_json_file.film_json>
|
|:Films :[films.id] {
| a schema:Movie ;
| schema:name [films.name] @en ;
| :year dbr:[films.year] ;
| schema:countryOfOrigin dbr:[films.country] ;
Expand All @@ -63,11 +64,13 @@ class FilmsTest extends AnyFunSuite with SHACLValidation {
|}
|
|:Actor dbr:[films.actors.name] {
| a schema:Actor ;
| :name [films.actors.name] ;
| :appear_on :[films.actors.film] ;
|}
|
|:Actress dbr:[films.actresses.name] {
| a schema:Actor ;
| :name [films.actresses.name] ;
| :appear_on :[films.actresses.film] ;
|}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.herminiogarcia.shexml.shex

import com.herminiogarcia.shexml.MappingLauncher
import org.scalatest.funsuite.AnyFunSuite

class FilmsWithInferredShapeMapAndBNodesTest extends AnyFunSuite with ShExValidation {

private val example =
"""
|PREFIX : <http://example.com/>
|PREFIX xs: <http://www.w3.org/2001/XMLSchema#>
|PREFIX dbr: <http://dbpedia.org/resource/>
|PREFIX schema: <http://schema.org/>
|SOURCE films_xml_file <https://shexml.herminiogarcia.com/files/films.xml>
|SOURCE films_json_file <https://shexml.herminiogarcia.com/files/films.json>
|ITERATOR film_xml <xpath: //film> {
| FIELD id <@id>
| FIELD name <name>
| FIELD year <year>
| FIELD country <country>
| FIELD directors <crew/directors/director>
| FIELD screenwritters <crew//screenwritter>
| FIELD music <crew/music>
| FIELD photography <crew/photography>
| ITERATOR actors <cast/actor> {
| FIELD name <name>
| FIELD role <role>
| FIELD film <../../@id>
| }
| ITERATOR actresses <cast/actress> {
| FIELD name <name>
| FIELD role <role>
| FIELD film <../../@id>
| }
|}
|ITERATOR film_json <jsonpath: $.films[*]> {
| PUSHED_FIELD id <id>
| FIELD name <name>
| FIELD year <year>
| FIELD country <country>
| FIELD directors <crew.director>
| FIELD screenwritters <crew.screenwritter>
| FIELD music <crew.music>
| FIELD photography <crew.cinematography>
| ITERATOR actors <cast[*]> {
| FIELD name <name>
| FIELD role <role>
| POPPED_FIELD film <id>
| }
|}
|EXPRESSION films <films_xml_file.film_xml UNION films_json_file.film_json>
|
|:Films :[films.id] {
| a schema:Movie ;
| schema:name [films.name] @en ;
| :year dbr:[films.year] ;
| schema:countryOfOrigin dbr:[films.country] ;
| schema:director dbr:[films.directors] ;
| :screenwritter dbr:[films.screenwritters] ;
| schema:musicBy dbr:[films.music] ;
| :cinematographer dbr:[films.photography] ;
| schema:actor @:Actor ;
| schema:actor @:Actress ;
|}
|
|:Actor _:[films.actors.name] {
| :name [films.actors.name] ;
| :appear_on :[films.actors.film] ;
|}
|
|:Actress _:[films.actresses.name] {
| :name [films.actresses.name] ;
| :appear_on :[films.actresses.film] ;
|}
""".stripMargin

test("Films validate against generated schema") {
val shapeMap = new MappingLauncher(normaliseURIs = true).launchShapeMapGeneration(example)
assert(this.validate(example, shapeMap))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class FilmsWithInferredShapeMapTest extends AnyFunSuite with ShExValidation {
|EXPRESSION films <films_xml_file.film_xml UNION films_json_file.film_json>
|
|:Films :[films.id] {
| a schema:Movie ;
| schema:name [films.name] @en ;
| :year dbr:[films.year] ;
| schema:countryOfOrigin dbr:[films.country] ;
Expand Down

0 comments on commit 6780ba4

Please sign in to comment.