Skip to content

Commit

Permalink
Added support for owl:imports in SHACL
Browse files Browse the repository at this point in the history
  • Loading branch information
labra committed Aug 20, 2018
1 parent 6da566b commit e43cf7c
Show file tree
Hide file tree
Showing 47 changed files with 734 additions and 215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ object Shacl2ShEx {
private def cnvComponents(cs: List[shacl.Component]): Result[List[shex.ShapeExpr]] =
sequence(cs.map(cnvComponent(_)))

private def cnvPropertyShapes(ps: List[shacl.ShapeRef],
private def cnvPropertyShapes(ps: List[shacl.RefNode],
schema: shacl.Schema
): Result[List[shex.ShapeExpr]] =
sequence(ps.map(cnvPropertyShapeRef(_, schema)))
Expand Down Expand Up @@ -138,7 +138,7 @@ object Shacl2ShEx {
_ <- modify(_.addLabelTripleExpr(lbl,te))
} yield (())

private def cnvPropertyShapeRef(sref: shacl.ShapeRef,
private def cnvPropertyShapeRef(sref: shacl.RefNode,
schema: shacl.Schema
): Result[shex.ShapeExpr] =
for {
Expand Down Expand Up @@ -252,7 +252,7 @@ object Shacl2ShEx {
}
}

private def getShape(sref: shacl.ShapeRef,
private def getShape(sref: shacl.RefNode,
schema: shacl.Schema
): Result[shacl.Shape] = {
fromEither(schema.shape(sref.id))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,30 @@ object ShEx2Shacl {
}

private type Err = String
private type ShapesMap = Map[shacl.ShapeRef, shacl.Shape]
private type ShapeExprsMap = Map[shex.ShapeExpr, shacl.ShapeRef]
private type TripleExprsMap = Map[shex.TripleExpr, shacl.ShapeRef]
private type ShapesMap = Map[shacl.RefNode, shacl.Shape]
private type ShapeExprsMap = Map[shex.ShapeExpr, shacl.RefNode]
private type TripleExprsMap = Map[shex.TripleExpr, shacl.RefNode]

private case class State(shapesMap: ShapesMap,
shapeExprsMap: ShapeExprsMap,
tripleExprsMap: TripleExprsMap,
counter: Int
) {

def addShapeRefShape(sref: ShapeRef, s: Shape): State =
def addShapeRefShape(sref: RefNode, s: Shape): State =
this.copy(shapesMap = shapesMap.updated(sref,s))

def newShapeExprRef(se: shex.ShapeExpr): (State, shacl.ShapeRef) = {
val id = ShapeRef(BNode("B" + counter))
def newShapeExprRef(se: shex.ShapeExpr): (State, shacl.RefNode) = {
val id = RefNode(BNode("B" + counter))
(this.copy(
shapeExprsMap = shapeExprsMap.updated(se, id),
counter = counter + 1
), id
)
}

def newTripleExprRef(te: shex.TripleExpr): (State, shacl.ShapeRef) = {
val id = ShapeRef(BNode("B" + counter))
def newTripleExprRef(te: shex.TripleExpr): (State, shacl.RefNode) = {
val id = RefNode(BNode("B" + counter))
(this.copy(
tripleExprsMap = tripleExprsMap.updated(te, id),
counter = counter + 1
Expand Down Expand Up @@ -78,7 +78,7 @@ object ShEx2Shacl {
private def setState(s: State): Result[Unit] =
EitherT.liftF(StateT.set(s))

private def addShapeRefShape(ref: ShapeRef, shape: Shape): Result[Unit] =
private def addShapeRefShape(ref: RefNode, shape: Shape): Result[Unit] =
EitherT.liftF(StateT.modify(_.addShapeRefShape(ref,shape)))

private def getShapesMap: Result[ShapesMap] =
Expand All @@ -88,18 +88,24 @@ object ShEx2Shacl {
private def getSchema(schema: shex.Schema): Result[shacl.Schema] = for {
_ <- getShaclShapes(schema)
smap <- getShapesMap
} yield shacl.Schema(pm = schema.prefixMap, shapesMap = smap)
} yield shacl.Schema(
pm = schema.prefixMap,
imports = List(),
entailments = List(),
shapesMap = smap,
propertyGroups = Map()
)

/* private def cnvPrefixMap(pm: PrefixMap): Map[String, IRI] = {
pm.pm.map { case (prefix, value) => (prefix.str, value) }
} */

private def getShaclShapes(schema: shex.Schema): Result[Map[shacl.ShapeRef, shacl.Shape]] = {
private def getShaclShapes(schema: shex.Schema): Result[Map[shacl.RefNode, shacl.Shape]] = {
val shexShapes: List[shex.ShapeExpr] = schema.shapes.getOrElse(List())
sequence(shexShapes.map(s => cnvShapeRefShape(s,schema))).map(_.toMap)
}

private type ShapeRefShape = (shacl.ShapeRef, shacl.Shape)
private type ShapeRefShape = (shacl.RefNode, shacl.Shape)

private def cnvShapeRefShape(s: shex.ShapeExpr,
schema: shex.Schema
Expand Down Expand Up @@ -156,7 +162,7 @@ object ShEx2Shacl {
id: RDFNode
): Result[shacl.Shape] = for {
ps <- shape.expression match {
case None => ok(List[(shacl.PropertyShape,shacl.ShapeRef)]())
case None => ok(List[(shacl.PropertyShape,shacl.RefNode)]())
case Some(te) => cnvTripleExpr(te, schema, id)
}
} yield {
Expand All @@ -165,7 +171,7 @@ object ShEx2Shacl {

private def outCast[A,B >: A](r:Result[A]): Result[B] = r.map(x => x)

private def cnvTripleExpr(te: shex.TripleExpr, schema: shex.Schema, id: RDFNode): Result[List[(shacl.PropertyShape, shacl.ShapeRef)]] = {
private def cnvTripleExpr(te: shex.TripleExpr, schema: shex.Schema, id: RDFNode): Result[List[(shacl.PropertyShape, shacl.RefNode)]] = {
te match {
case e: shex.EachOf => err(s"cnvTripleExpr: Not implemented EachOf $e conversion yet")
case e: shex.OneOf => err(s"cnvTripleExpr: Not implemented OneOf $e conversion yet")
Expand All @@ -178,7 +184,7 @@ object ShEx2Shacl {
private def cnvTripleConstraint(tc: shex.TripleConstraint,
schema: shex.Schema,
id: RDFNode
): Result[(shacl.PropertyShape, shacl.ShapeRef)] = {
): Result[(shacl.PropertyShape, shacl.RefNode)] = {
if (tc.negated)
err(s"cnvTripleConstraint: Not implemented negated")
else {
Expand Down Expand Up @@ -218,7 +224,7 @@ object ShEx2Shacl {
ps: PropertyShape = Shape.emptyPropertyShape(id, path).copy(
components = components
)
_ <- addShapeRefShape(ShapeRef(id), ps)
_ <- addShapeRefShape(RefNode(id), ps)
} yield ps
rs
}
Expand Down Expand Up @@ -246,9 +252,9 @@ object ShEx2Shacl {
private def getShapeExprsMap: Result[ShapeExprsMap] = getState.map(_.shapeExprsMap)
private def getTripleExprsMap: Result[TripleExprsMap] = getState.map(_.tripleExprsMap)

private def getShapeExprId(se: shex.ShapeExpr): Result[ShapeRef] = se.id match {
case Some(shex.IRILabel(iri)) => ok(ShapeRef(iri))
case Some(shex.BNodeLabel(bnode)) => ok(ShapeRef(bnode))
private def getShapeExprId(se: shex.ShapeExpr): Result[RefNode] = se.id match {
case Some(shex.IRILabel(iri)) => ok(RefNode(iri))
case Some(shex.BNodeLabel(bnode)) => ok(RefNode(bnode))
case None => for {
shapeExprsMap <- getShapeExprsMap
id <- shapeExprsMap.get(se) match {
Expand All @@ -262,9 +268,9 @@ object ShEx2Shacl {
} yield id
}

private def getTripleExprId(te: shex.TripleExpr): Result[ShapeRef] = te.id match {
case Some(shex.IRILabel(iri)) => ok(ShapeRef(iri))
case Some(shex.BNodeLabel(bnode)) => ok(ShapeRef(bnode))
private def getTripleExprId(te: shex.TripleExpr): Result[RefNode] = te.id match {
case Some(shex.IRILabel(iri)) => ok(RefNode(iri))
case Some(shex.BNodeLabel(bnode)) => ok(RefNode(bnode))
case None => for {
tripleExprsMap <- getTripleExprsMap
id <- tripleExprsMap.get(te) match {
Expand Down
17 changes: 13 additions & 4 deletions modules/schema/src/main/scala/es/weso/schema/ShaclexSchema.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cats.implicits._
import es.weso.rdf._
import es.weso.rdf.nodes._
import es.weso.rdf.jena.RDFAsJenaModel
import es.weso.shacl.SHACLPrefixes.owl_imports
import es.weso.shacl.{Schema => ShaclSchema, _}
// import es.weso.shacl._
import es.weso.shacl.converter.{RDF2Shacl, Shacl2ShEx}
Expand Down Expand Up @@ -98,13 +99,21 @@ case class ShaclexSchema(schema: ShaclSchema) extends Schema {
override def fromString(cs: CharSequence, format: String, base: Option[String]): Either[String, Schema] = {
for {
rdf <- RDFAsJenaModel.fromChars(cs, format, base)
schema <- RDF2Shacl.getShacl(rdf)
schema <- RDF2Shacl.getShacl(rdf, true)
} yield ShaclexSchema(schema)
}

override def fromRDF(rdf: RDFReader): Either[String, Schema] = for {
schemaShacl <- RDF2Shacl.getShacl(rdf)
} yield ShaclexSchema(schemaShacl)
override def fromRDF(rdf: RDFReader): Either[String, Schema] = rdf.asRDFBuilder match {
case Left(_) => rdf.triplesWithPredicate(owl_imports).size match {
case 0 => RDF2Shacl.getShaclFromRDFReader(rdf).map(ShaclexSchema(_))
case _ => Left(s"Nor supported owl:imports for this kind of RDF model")
}
case Right(rdfBuilder) =>
for {
schemaShacl <- RDF2Shacl.getShacl(rdfBuilder, true)
} yield ShaclexSchema(schemaShacl)
}


override def serialize(format: String): Either[String, String] = {
val builder: RDFBuilder = RDFAsJenaModel.empty
Expand Down
12 changes: 6 additions & 6 deletions modules/shacl/src/main/scala/es/weso/shacl/Component.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,22 @@ case class LessThan(p: IRI) extends Component {
case class LessThanOrEquals(p: IRI) extends Component {
override val name: String = "lessThanOrEquals"
}
case class Or(shapes: List[ShapeRef]) extends Component {
case class Or(shapes: List[RefNode]) extends Component {
override val name: String = "or"
}
case class And(shapes: List[ShapeRef]) extends Component {
case class And(shapes: List[RefNode]) extends Component {
override val name: String = "and"
}
case class Not(shape: ShapeRef) extends Component {
case class Not(shape: RefNode) extends Component {
override val name: String = "not"
}
case class Xone(shapes: List[ShapeRef]) extends Component {
case class Xone(shapes: List[RefNode]) extends Component {
override val name: String = "xone"
}
case class Closed(isClosed: Boolean, ignoredProperties: List[IRI]) extends Component {
override val name: String = "closed"
}
case class NodeComponent(shape: ShapeRef) extends Component {
case class NodeComponent(shape: RefNode) extends Component {
override val name: String = "node"
}
case class HasValue(value: Value) extends Component {
Expand All @@ -87,7 +87,7 @@ case class In(list: List[Value]) extends Component {

// TODO: Change representation to include optional parent shape
case class QualifiedValueShape(
shape: ShapeRef,
shape: RefNode,
qualifiedMinCount: Option[Int],
qualifiedMaxCount: Option[Int],
qualifiedValueShapesDisjoint: Option[Boolean]) extends Component {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package es.weso.shacl
import es.weso.rdf.nodes.{DecimalLiteral, RDFNode}

case class PropertyGroup(
order: Option[DecimalLiteral],
label: Set[RDFNode]
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ package es.weso.shacl

import es.weso.rdf.nodes.RDFNode

case class ShapeRef(id: RDFNode) extends AnyVal {
case class RefNode(id: RDFNode) extends AnyVal {
def showId = id.toString
}
12 changes: 10 additions & 2 deletions modules/shacl/src/main/scala/es/weso/shacl/SHACLPrefixes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ object SHACLPrefixes {
lazy val sh_description: IRI = sh + "description"
lazy val sh_disjoint: IRI = sh + "disjoint"
lazy val sh_equals: IRI = sh + "equals"
lazy val sh_entailment: IRI = sh + "entailment"
lazy val sh_flags: IRI = sh + "flags"
lazy val sh_focusNode: IRI = sh + "focusNode"
lazy val sh_group: IRI = sh + "group"
lazy val sh_hasValue: IRI = sh + "hasValue"
lazy val sh_ignoredProperties: IRI = sh + "ignoredProperties"
lazy val sh_in: IRI = sh + "in"
Expand All @@ -51,11 +53,12 @@ object SHACLPrefixes {
lazy val sh_minLength: IRI = sh + "minLength"
lazy val sh_maxLength: IRI = sh + "maxLength"
lazy val sh_message: IRI = sh + "message"
lazy val sh_nodeKind: IRI = sh + "nodeKind"
lazy val sh_name: IRI = sh + "name"
lazy val sh_nodeKind: IRI = sh + "nodeKind"
lazy val sh_node: IRI = sh + "node"
lazy val sh_not: IRI = sh + "not"
lazy val sh_or: IRI = sh + "or"
lazy val sh_order: IRI = sh + "order"
lazy val sh_path: IRI = sh + "path"
lazy val sh_pattern: IRI = sh + "pattern"
lazy val sh_property: IRI = sh + "property"
Expand All @@ -67,6 +70,7 @@ object SHACLPrefixes {
lazy val sh_resultPath: IRI = sh + "resultPath"
lazy val sh_resultSeverity: IRI = sh + "resultSeverity"
lazy val sh_resultMessage: IRI = sh + "resultMessage"
lazy val sh_shapesGraph: IRI = sh + "shapesGraph"
lazy val sh_severity: IRI = sh + "severity"
lazy val sh_sourceConstraintComponent: IRI = sh + "sourceConstraintComponent"
lazy val sh_sourceShape: IRI = sh + "sourceShape"
Expand All @@ -79,11 +83,15 @@ object SHACLPrefixes {
lazy val sh_uniqueLang: IRI = sh + "uniqueLang"
lazy val sh_xone: IRI = sh + "xone"

lazy val owl_imports: IRI = owl + "imports"

lazy val defaultPrefixMap = PrefixMap(
Map(
Prefix("sh") -> sh,
Prefix("rdf") -> rdf,
Prefix("xsd") -> xsd,
Prefix("rdfs") -> rdfs))
Prefix("rdfs") -> rdfs,
Prefix("owl") -> owl
))

}
Loading

0 comments on commit e43cf7c

Please sign in to comment.