Skip to content

Commit

Permalink
Added support for deactivated...started support for sh:message
Browse files Browse the repository at this point in the history
  • Loading branch information
labra committed Aug 17, 2018
1 parent f418a64 commit 718dcf7
Show file tree
Hide file tree
Showing 19 changed files with 523 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,48 @@ package es.weso.shacl.converter
import cats.Id
import cats.data._
import cats.implicits._
import es.weso.rdf.PrefixMap
import es.weso.rdf.nodes._
import es.weso.rdf.path.{InversePath, PredicatePath, SHACLPath}
import es.weso.{shacl, _}

object Shacl2ShEx {

def shacl2ShEx(schema: shacl.Schema): Either[String, shex.Schema] =
cnvSchema(schema).value
def shacl2ShEx(schema: shacl.Schema): Either[String, (shex.Schema, shapeMaps.QueryShapeMap)] = {
val (state, eitherSchema) = cnvSchema(schema).value.run(initialState)
for {
schema <- eitherSchema
schema1 = schema.addTripleExprMap(state.tripleExprMap)
queryMap <- cnvShapeMap(schema)
} yield (schema1,queryMap)
}

def cnvShapeMap(schema: shex.Schema): Either[String,shapeMaps.QueryShapeMap] = Right(shapeMaps.QueryShapeMap(List(), PrefixMap.empty, PrefixMap.empty))

case class State(tripleExprMap: TEMap) {
def addLabelTripleExpr(lbl: shex.ShapeLabel, te: shex.TripleExpr): State = {
this.copy(tripleExprMap = tripleExprMap.updated(lbl,te))
}
}

lazy val initialState: State = State(Map())

type TEMap = Map[shex.ShapeLabel, shex.TripleExpr]

private type Result[A] = EitherT[Id,String,A]
type S[A] = StateT[Id,State,A]

private type Result[A] = EitherT[S,String,A]

private def ok[A](x:A): Result[A] =
EitherT.pure(x)

private def err[A](msg: String): Result[A] = {
EitherT.leftT[Id,A](msg)
EitherT.leftT[S,A](msg)
}

private def modify(fn: State => State): Result[Unit] =
EitherT.liftF(StateT.modify(fn))

private def sequence[A](rs: List[Result[A]]): Result[List[A]] = rs.sequence[Result,A]

private def cnvSchema(schema: shacl.Schema): Result[shex.Schema] = {
Expand Down Expand Up @@ -58,7 +82,7 @@ object Shacl2ShEx {
case s => err(s"cnvShape: Unimplemented conversion of $s")
}

private type ShExId = Option[shex.ShapeLabel]
// private type ShExId = Option[shex.ShapeLabel]

private def cnvId(node: RDFNode): Result[shex.ShapeLabel] =
shex.ShapeLabel.fromRDFNode(node).fold(e => err(e), lbl => ok(lbl))
Expand All @@ -68,7 +92,7 @@ object Shacl2ShEx {

private def cnvPropertyShapes(ps: List[shacl.ShapeRef],
schema: shacl.Schema
): Result[List[shex.TripleExpr]] =
): Result[List[shex.ShapeExpr]] =
sequence(ps.map(cnvPropertyShapeRef(_, schema)))

private def cnvNodeShape(ns: shacl.NodeShape,
Expand All @@ -77,15 +101,20 @@ object Shacl2ShEx {
for {
id <- cnvId(ns.id)
maybeSe <- cnvComponentsAsShapeExpr(ns.components)
_ <- { println(s"MaybeSe: $maybeSe"); ok(()) }
ps <- cnvPropertyShapes(ns.propertyShapes.toList, schema)
_ <- { println(s"ps: $ps"); ok(()) }
se = maybeSe.getOrElse(shex.ShapeExpr.any)
se1 <- ps.length match {
se1 = ps.length match {
case 0 => // TODO: Check when there are more triple exprs...
ok(se)
case 1 =>
addExpression(se, ps.head)
se
case 1 => {
println(s"Length 1...")
ps.head // addExpression(se, ps.head)
}
case n if (n > 1) =>
addExpression(se, shex.EachOf(None,ps,None,None,None,None))
// addExpression(se, shex.EachOf(None,ps,None,None,None,None))
shex.ShapeAnd(None, ps)
}
se2 <- addId(se1,id)
} yield se2
Expand All @@ -94,31 +123,44 @@ object Shacl2ShEx {
ok(se.addId(id))
}

private def addExpression(se: shex.ShapeExpr, te: shex.TripleExpr): Result[shex.ShapeExpr] = se match {
/* private def addExpression(se: shex.ShapeExpr, te: shex.TripleExpr): Result[shex.ShapeExpr] = se match {
case s: shex.Shape => ok(s.copy(expression = Some(te)))
case nc: shex.NodeConstraint => ok(shex.ShapeAnd(None,
List(nc,
shex.Shape.empty.copy(expression=Some(te))))
)
}
}*/

private def addLabelTripleExpr(lbl: shex.ShapeLabel,
te: shex.TripleExpr
): Result[Unit] =
for {
_ <- modify(_.addLabelTripleExpr(lbl,te))
} yield (())

private def cnvPropertyShapeRef(sref: shacl.ShapeRef,
schema: shacl.Schema): Result[shex.TripleExpr] =
schema: shacl.Schema
): Result[shex.ShapeExpr] =
for {
shape <- getShape(sref, schema)
te <- shape match {
case ps: shacl.PropertyShape => cnvPropertyShape(ps)
case _ => err(s"cnvPropertyShapeRef: reference $sref does not point to a property shape. Shape: $shape")
se <- shape match {
case ps: shacl.PropertyShape => for {
id <- cnvId(ps.id)
s <- cnvPropertyShape(ps)
_ <- addLabelTripleExpr(id,s)
} yield shapeInclusion(id)
case _ =>
err[shex.ShapeExpr](s"cnvPropertyShapeRef: reference $sref does not point to a property shape. Shape: $shape")
}
} yield te
} yield se

private def cnvPropertyShape(ps: shacl.PropertyShape): Result[shex.TripleExpr] =
for {
id <- cnvId(ps.id)
predicateInverse <- getPredicateInversePair(ps.path)
se <- cnvComponentsAsShapeExpr(ps.components)
min <- getMinComponent(ps.components)
max <- getMaxComponent(ps.components)
} yield shex.TripleConstraint(Some(id),predicateInverse.inverse, None, predicateInverse.pred, se, min, max, None, None, None)
} yield shex.TripleConstraint(None,predicateInverse.inverse, None, predicateInverse.pred, se, min, max, None, None, None)

case class PredicateInverse(pred: IRI, inverse: Option[Boolean])

Expand Down Expand Up @@ -175,9 +217,11 @@ object Shacl2ShEx {
}
}

private lazy val shexIri: shex.ShapeExpr = shex.NodeConstraint.nodeKind(shex.IRIKind, List())
private lazy val shexBNode: shex.ShapeExpr = shex.NodeConstraint.nodeKind(shex.BNodeKind, List())
private lazy val shexLiteral: shex.ShapeExpr = shex.NodeConstraint.nodeKind(shex.LiteralKind, List())
private def shexIri(): shex.ShapeExpr = shex.NodeConstraint.nodeKind(shex.IRIKind, List())
private def shexBNode(): shex.ShapeExpr = shex.NodeConstraint.nodeKind(shex.BNodeKind, List())
private def shexLiteral(): shex.ShapeExpr = shex.NodeConstraint.nodeKind(shex.LiteralKind, List())
private def shapeInclusion(lbl: shex.ShapeLabel): shex.ShapeExpr =
shex.Shape.empty.copy(expression = Some(shex.Inclusion(lbl)))

private def cnvNodeKind(nk: shacl.NodeKind): Result[shex.ShapeExpr] =
nk.value match {
Expand Down Expand Up @@ -217,10 +261,10 @@ object Shacl2ShEx {
private def fromEither[A](e: Either[String,A]): Result[A] =
EitherT.fromEither(e)

private def mkIRILabel(iri: IRI): shex.ShapeLabel =
/* private def mkIRILabel(iri: IRI): shex.ShapeLabel =
shex.IRILabel(iri)
private def mkBNodeLabel(n: Int): shex.ShapeLabel =
shex.BNodeLabel(BNode(n.toString))

*/
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package es.weso.shex.converter
import cats._
import cats.data._
import cats.implicits._
import es.weso.shex._

object CountUsages {

def countUsages(schema: Schema): Either[String, Map[ShapeLabel,Int]] = {
val (visited,eitherUsages) = countUsagesSchema.value.run(iniitialVisited).run(schema)
eitherUsages
}

private lazy val iniitialVisited: Visited = Set()
type Visited = Set[ShapeLabel]
type SchemaReader[A] = ReaderT[Id,Schema,A]
type S[A] = StateT[SchemaReader,Visited,A]
type Err = String
type Result[A] = EitherT[S,Err,A]

private def ok[A](x: A): Result[A] = EitherT.pure[S,Err](x) // StateT[SchemaReader,Visited,A].pure(x)
private def err[A](str: String): Result[A] = EitherT.leftT[S,A](str)
private def getVisited: Result[Visited] = EitherT.liftF[S,Err,Visited](StateT.get[SchemaReader,Visited])
private def modifyVisited(fn: Visited => Visited): Result[Unit] = EitherT.liftF[S,Err,Unit](StateT.modify[SchemaReader,Visited](fn))
private def addVisited(lbl: ShapeLabel):Result[Unit] =
modifyVisited(visited => visited + lbl)
private def getSchema: Result[Schema] = EitherT.liftF[S,Err,Schema](StateT.liftF[SchemaReader,Visited,Schema](Kleisli.ask))
private def sequence[A](ls: List[Result[A]]): Result[List[A]] = ls.sequence[Result,A]
private def getShape(lbl: ShapeLabel): Result[ShapeExpr] = for {
schema <- getSchema
se <- schema.getShape(lbl).
fold(err[ShapeExpr](s"Not found shape with label $lbl"))(ok(_))
} yield se

private def isBNode(lbl: ShapeLabel): Boolean = lbl match {
case _: BNodeLabel => true
case _ => false
}

private def tripleExprBNodeLabels(schema: Schema): List[ShapeLabel] =
schema.tripleExprMap.getOrElse(Map()).keys.toList.filter(isBNode(_))

private def countUsagesSchema: Result[Map[ShapeLabel,Int]] = for {
schema <- getSchema
usages <- sequence(tripleExprBNodeLabels(schema).map(countUsagesLabel(_)))
} yield usages.toMap

private def countUsagesLabel(lbl: ShapeLabel): Result[(ShapeLabel, Int)] = {
def zero = ok(0)
def comb(r: Result[Int], se: ShapeExpr): Result[Int] = for {
c <- countUsagesLabelShapeExpr(lbl,se)
n <- r
} yield n + c
for {
schema <- getSchema
count <- schema.shapeList.foldLeft(zero)(comb)
} yield {
(lbl, count)
}
}

private def countUsagesLabelShapeExpr(lbl: ShapeLabel, se: ShapeExpr): Result[Int] =
se match {
case ShapeAnd(_, ses) => sequence(ses.map(countUsagesLabelShapeExpr(lbl,_))).map(_.sum)
case ShapeOr(_,ses) => sequence(ses.map(countUsagesLabelShapeExpr(lbl,_))).map(_.sum)
case ShapeNot(_,se) => countUsagesLabelShapeExpr(lbl,se)
case nk: NodeConstraint => ok(0)
case s: Shape => s.expression.fold(ok(0))(countUsagesLabelTripleExpr(lbl,_))
case ShapeExternal(_) => ok(0)
case ShapeRef(lbl) => for {
visited <- getVisited
n <- if (visited contains lbl) ok(0)
else for {
_ <- addVisited(lbl)
shape <- getShape(lbl)
n <- countUsagesLabelShapeExpr(lbl,shape)
} yield n
} yield n
}

private def countUsagesLabelTripleExpr(lbl: ShapeLabel, te: TripleExpr): Result[Int] =
te match {
case e: EachOf => sequence(e.expressions.map(countUsagesLabelTripleExpr(lbl,_))).map(_.sum)
case e: OneOf => sequence(e.expressions.map(countUsagesLabelTripleExpr(lbl,_))).map(_.sum)
case Inclusion(includeLbl) =>
if (lbl == includeLbl) ok(1)
else ok(0)
case e: Expr => ok(0)
case tc: TripleConstraint => tc.valueExpr.fold(ok(0))(countUsagesLabelShapeExpr(lbl,_))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import es.weso._
import es.weso.shacl._
import es.weso.rdf.nodes._
import es.weso.rdf.path._
import es.weso.rdf.PrefixMap
import cats.implicits._
import es.weso.shapeMaps.QueryShapeMap
import es.weso.shex.ValueSetValue
Expand Down Expand Up @@ -91,9 +90,9 @@ object ShEx2Shacl {
smap <- getShapesMap
} yield shacl.Schema(pm = schema.prefixMap, shapesMap = smap)

private def cnvPrefixMap(pm: PrefixMap): Map[String, IRI] = {
/* 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]] = {
val shexShapes: List[shex.ShapeExpr] = schema.shapes.getOrElse(List())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package es.weso.shex.converter

import es.weso.shex._
import cats._
import cats.implicits._

trait ShExSimplifier {
def inlineInclusions(schema: Schema): Either[String,Schema] = {
for {
usages <- CountUsages.countUsages(schema)
inlined <- inlineInclusionLabels(usages.toList.collect { case (lbl,c) if c == 1 => lbl}, schema)
} yield {
inlined
}
}

def inlineInclusionLabels(ls: List[ShapeLabel], schema: Schema): Either[String, Schema] = {
val zero: Either[String, Schema] = Right(schema)
ls.foldLeft(zero)(inlineInclusion)
}

def inlineInclusion(r: Either[String,Schema], lbl: ShapeLabel): Either[String, Schema] = for {
currentSchema <- r
next <- inline(currentSchema, lbl)
} yield next

def inline(schema: Schema, lbl: ShapeLabel): Either[String, Schema] = for {
te <- schema.getTripleExprMap.get(lbl).toRight(s"Error obtaining label $lbl in map: ${schema.getTripleExprMap()}")
} yield ???

}
Loading

0 comments on commit 718dcf7

Please sign in to comment.