diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..f4a3ef70
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# CHANGELOG
+
+## v0.2.34 - 2025-04-25
+
+Added option to show dependency graph and repaired issue #623
diff --git a/build.sbt b/build.sbt
index 42855d7f..83d33ccb 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,13 +1,13 @@
-lazy val scala212 = "2.12.17"
-lazy val scala213 = "2.13.10"
-lazy val scala3 = "3.2.1"
+lazy val scala212 = "2.12.20"
+lazy val scala213 = "2.13.15"
+lazy val scala3 = "3.6.3"
lazy val supportedScalaVersions = List(
- scala3,
+ scala212,
scala213,
- scala212
+ scala3
)
-val Java11 = JavaSpec.temurin("11")
+val Java11 = JavaSpec.temurin("11")
lazy val srdfVersion = "0.1.125"
lazy val utilsVersion = "0.2.25"
@@ -19,7 +19,7 @@ lazy val catsVersion = "2.9.0"
lazy val catsEffectVersion = "3.4.4"
lazy val circeVersion = "0.14.2"
lazy val commonsTextVersion = "1.8"
-lazy val declineVersion = "2.4.1"
+lazy val declineVersion = "2.5.0"
lazy val fansiVersion = "0.3.0"
lazy val fs2Version = "3.4.0"
lazy val jenaVersion = "4.3.2"
@@ -73,7 +73,6 @@ lazy val wdtkUtil = "org.wikidata.wdtk" % "wdtk-util" % wikidataToolkitVersion
lazy val scalacheck = "org.scalacheck" %% "scalacheck" % scalacheckVersion
lazy val typesafeConfig = "com.typesafe" % "config" % typesafeConfigVersion
-
lazy val logbackClassic = "ch.qos.logback" % "logback-classic" % logbackVersion
lazy val scalaLogging =
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion
@@ -142,8 +141,8 @@ lazy val shexs = project
catsEffect,
decline,
declineEffect,
- slf4jAPI,
- slf4jSimple,
+ // slf4jAPI,
+ // slf4jSimple,
srdf,
srdf4j,
srdfJena,
@@ -252,7 +251,7 @@ lazy val wshex = project
.settings(
crossScalaVersions := supportedScalaVersions,
libraryDependencies ++= Seq(
- utils,
+ utils,
catsCore,
catsKernel,
circeCore,
@@ -269,7 +268,7 @@ lazy val wshex = project
scalaCollCompat,
srdfJena,
munit % Test,
- munitEffect % Test,
+ munitEffect % Test
),
testFrameworks += new TestFramework("munit.Framework")
)
@@ -580,6 +579,8 @@ lazy val commonSettings = compilationSettings ++ sharedDependencies ++ Seq(
email = "jelabra@gmail.com",
url = url("https://weso.labra.es")
)
- ),
- libraryDependencies += compilerPlugin("com.github.ghik" % "zerowaste" % "0.2.1" cross CrossVersion.full)
+ )
+ /*libraryDependencies += compilerPlugin(
+ ("com.github.ghik" % "zerowaste" % "1.0.0").cross(CrossVersion.full)
+ )*/
) ++ warnUnusedImport
diff --git a/examples/non_stratified.shex b/examples/non_stratified.shex
new file mode 100644
index 00000000..50bffd22
--- /dev/null
+++ b/examples/non_stratified.shex
@@ -0,0 +1,3 @@
+prefix :
+
+:S { :p NOT @:S }
\ No newline at end of file
diff --git a/examples/positive_recursion.shex b/examples/positive_recursion.shex
new file mode 100644
index 00000000..ae0916af
--- /dev/null
+++ b/examples/positive_recursion.shex
@@ -0,0 +1,4 @@
+prefix :
+
+# Positive recursion
+:S { :p @:S +; :p .* } OR [ :d ]
diff --git a/examples/separation.shex b/examples/separation.shex
new file mode 100644
index 00000000..ae95e14a
--- /dev/null
+++ b/examples/separation.shex
@@ -0,0 +1,5 @@
+prefix :
+
+# Separation test
+:S { :p @:S + }
+:S1 NOT @:S
\ No newline at end of file
diff --git a/examples/separation1.shex b/examples/separation1.shex
new file mode 100644
index 00000000..e6a66b7d
--- /dev/null
+++ b/examples/separation1.shex
@@ -0,0 +1,4 @@
+prefix :
+
+# Separation test 1
+:S { :p @:S + }
diff --git a/examples/separation2.shex b/examples/separation2.shex
new file mode 100644
index 00000000..e6a66b7d
--- /dev/null
+++ b/examples/separation2.shex
@@ -0,0 +1,4 @@
+prefix :
+
+# Separation test 1
+:S { :p @:S + }
diff --git a/examples/separation4.shex b/examples/separation4.shex
new file mode 100644
index 00000000..ae95e14a
--- /dev/null
+++ b/examples/separation4.shex
@@ -0,0 +1,5 @@
+prefix :
+
+# Separation test
+:S { :p @:S + }
+:S1 NOT @:S
\ No newline at end of file
diff --git a/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraph.scala b/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraph.scala
index 9900fb1f..60748ba9 100644
--- a/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraph.scala
+++ b/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraph.scala
@@ -48,10 +48,10 @@ trait DepGraph[Node] {
private def haveNegativeLink(node1: Node, node2: Node): Boolean =
edgeBetween(node1, node2) match {
- case Some(Neg) => true
- case Some(Pos) => false
- case Some(Both) => true
- case None => false
+ case Some(Neg) => true
+ case Some(Pos) => false
+ // case Some(Both) => true
+ case None => false
}
def showEdges(showNode: Node => String = x => x.toString): String
diff --git a/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraphJGraphT.scala b/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraphJGraphT.scala
index 5841a281..a33e466d 100644
--- a/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraphJGraphT.scala
+++ b/modules/depGraphs/src/main/scala/es/weso/depgraphs/DepGraphJGraphT.scala
@@ -46,7 +46,7 @@ case class DepGraphJGraphT[Node]() extends DepGraph[Node] with LazyLogging {
// if (!graph.containsVertex(node))
graph.addVertex(node)
- private def addEdge(node1: Node, node2: Node, edge: Edge): DepGraph[Node] = {
+ private def addEdgeInternal(node1: Node, node2: Node, edge: Edge): DepGraph[Node] = {
checkVertex(node1)
checkVertex(node2)
graph.addEdge(node1, node2, edge)
@@ -61,14 +61,19 @@ case class DepGraphJGraphT[Node]() extends DepGraph[Node] with LazyLogging {
checkVertex(node2)
this.edgeBetween(node1, node2) match {
case Some(pn) =>
+ // println(s"Edge between $node1 and $node2 already exists with posNeg $pn")
removeEdge(node1, node2)
- addEdge(node1, node2, Edge(node1, pn.combine(posNeg), node2))
- case None => addEdge(node1, node2, Edge(node1, posNeg, node2))
+ val newPosNeg = pn.combine(posNeg)
+ val result = addEdgeInternal(node1, node2, Edge(node1, newPosNeg, node2))
+ // println(s"New edge added $node1 and $node2 posNeg $newPosNeg")
+ result
+ case None => addEdgeInternal(node1, node2, Edge(node1, posNeg, node2))
}
}
override def edgeBetween(node1: Node, node2: Node): Option[PosNeg] = {
- val outEdges = graph.edgesOf(node1).asScala.toSet
+ val outEdges: Set[Edge] = graph.outgoingEdgesOf(node1).asScala.toSet
+ // println(s"outEdges($node1)=$outEdges")
outEdges.collect { case e: Edge if e.target == node2 => e.posNeg }.headOption
}
@@ -89,7 +94,7 @@ case class DepGraphJGraphT[Node]() extends DepGraph[Node] with LazyLogging {
}
private def containsNegEdge(g: Graph[Node, Edge]): Boolean =
- g.edgeSet.asScala.exists(e => e.posNeg == Neg || e.posNeg == Both)
+ g.edgeSet.asScala.exists(e => e.posNeg == Neg) // || e.posNeg == Both)
override def negCycles: Set[Set[(Node, Node)]] = {
val scAlg: StrongConnectivityAlgorithm[Node, Edge] =
@@ -112,9 +117,9 @@ case class DepGraphJGraphT[Node]() extends DepGraph[Node] with LazyLogging {
def showPosNeg(pn: PosNeg): String =
pn match {
- case Pos => "-(+)->"
- case Neg => "-(-)->"
- case Both => "-(-/+)->"
+ case Pos => "-(+)->"
+ case Neg => "-(-)->"
+ // case Both => "-(-/+)->"
}
def showEdges(showNode: Node => String): String = {
diff --git a/modules/depGraphs/src/main/scala/es/weso/depgraphs/PosNeg.scala b/modules/depGraphs/src/main/scala/es/weso/depgraphs/PosNeg.scala
index 36ef3a53..b19e228c 100644
--- a/modules/depGraphs/src/main/scala/es/weso/depgraphs/PosNeg.scala
+++ b/modules/depGraphs/src/main/scala/es/weso/depgraphs/PosNeg.scala
@@ -2,27 +2,29 @@ package es.weso.depgraphs
sealed trait PosNeg {
def change: PosNeg = this match {
- case Neg => Pos
- case Pos => Neg
- case Both => Both
+ case Neg => Pos
+ case Pos => Neg
+ // case Both => Both
}
def combine(other: PosNeg): PosNeg
}
case object Pos extends PosNeg {
override def combine(other: PosNeg): PosNeg = other match {
- case Pos => Pos
- case Neg => Both
- case Both => Both
+ case Pos => Pos
+ case Neg => Neg
+ // case Neg => Both
+ // case Both => Both
}
}
case object Neg extends PosNeg {
override def combine(other: PosNeg): PosNeg = other match {
- case Pos => Both
- case Neg => Neg
- case Both => Both
+ case Pos => Neg // Both
+ case Neg => Neg
+ // case Both => Both
}
}
-case object Both extends PosNeg {
+
+/*case object Both extends PosNeg {
override def combine(other: PosNeg): PosNeg = Both
-}
+}*/
diff --git a/modules/shex/src/main/scala/es/weso/shex/Dependencies.scala b/modules/shex/src/main/scala/es/weso/shex/Dependencies.scala
index 7a5d77a6..ff6c3f7e 100644
--- a/modules/shex/src/main/scala/es/weso/shex/Dependencies.scala
+++ b/modules/shex/src/main/scala/es/weso/shex/Dependencies.scala
@@ -22,14 +22,14 @@ object Dependencies {
* If the set is empy, there are no negated cycles.
*/
def negCycles(schema: Schema): ES[Set[Set[(ShapeLabel, ShapeLabel)]]] =
- depGraph(schema).map(_.negCycles)
+ schema.depGraph.map(_.negCycles)
def oddNegCycles(schema: Schema): ES[Set[Set[(ShapeLabel, ShapeLabel)]]] =
- depGraph(schema).map(_.oddNegCycles)
- /* for {
- dg <- depGraph(schema)
- negCycles = dg.negCycles.filter { nc => dg.countNegLinks(nc) % 2 == 1 }
- } yield negCycles */
+ // depGraph(schema).map(_.oddNegCycles)
+ for {
+ dg <- schema.depGraph
+ negCycles = dg.negCycles.filter(nc => dg.countNegLinks(nc) % 2 == 1)
+ } yield negCycles
/** Returns the dependency graph of a schema
*
@@ -42,7 +42,11 @@ object Dependencies {
case None => emptyGraph
case Some(shapes) => shapes.foldRight(emptyGraph)(addDependency(schema))
}
-// println(s"Dependency graph: $r")
+ /*r match {
+ case Left(s) => println(s"Error calculating dependency graph: $s")
+ case Right(g) =>
+ println(s"Dependency graph generated:\n${g.showEdges(_.toString)}\n---")
+ }*/
r
}
@@ -50,7 +54,7 @@ object Dependencies {
deps.foldRight(graph)(combine)
def combine(d: Dep, g: DepGraph[ShapeLabel]): DepGraph[ShapeLabel] =
-// println(s"Adding edge $d to graph: $g")
+ // println(s"Adding edge $d to graph: $g")
g.addEdge(d._1, d._2, d._3)
def addDependency(
@@ -60,13 +64,19 @@ object Dependencies {
g <- graph
label <- getLabel(se)
deps <- dependencies(schema, se, label, Pos)
+ // _ <- { println(s"dependencies: ${deps}"); Right(()) }
} yield addDependencies(g, deps)
def getLabel(se: ShapeExpr): ES[ShapeLabel] =
Either.fromOption(se.id, s"Shape $se has no label")
- def dependencies(schema: Schema, shape: ShapeExpr, source: ShapeLabel, posNeg: PosNeg): ES[Deps] =
- // println(s"Calculating dependencies of shape $shape with source label $source and posNeg $posNeg")
+ def dependencies(
+ schema: Schema,
+ shape: ShapeExpr,
+ source: ShapeLabel,
+ posNeg: PosNeg
+ ): ES[Deps] =
+ // println(s"Calculating dependencies of $source with shapeExpr $shape, posNeg $posNeg")
shape match {
case s: ShapeAnd =>
s.shapeExprs.map(dependencies(schema, _, source, posNeg)).sequence[ES, Deps].map(_.flatten)
@@ -75,7 +85,7 @@ object Dependencies {
s.shapeExprs.map(dependencies(schema, _, source, posNeg)).sequence[ES, Deps].map(_.flatten)
case s: ShapeNot =>
- dependencies(schema, s.shapeExpr, source, Neg)
+ dependencies(schema, s.shapeExpr, source, posNeg.change)
case _: NodeConstraint => noDeps
@@ -108,7 +118,6 @@ object Dependencies {
tripleExpr: TripleExpr,
posNeg: PosNeg
): ES[Deps] =
- // println(s"Calculating dependencies of tripleExpr $tripleExpr with source label $source and posNeg $posNeg")
tripleExpr match {
case t: EachOf =>
// TODO: Take into account max cardinality = 0 as a negative dependency?
@@ -134,7 +143,7 @@ object Dependencies {
case Some(ve) =>
if (tc.max == IntMax(0)) {
// TODO: Should it be negative dependency?
- dependencies(schema, ve, source, posNeg.change)
+ dependencies(schema, ve, source, posNeg)
} else {
dependencies(schema, ve, source, posNeg)
}
diff --git a/modules/shex/src/main/scala/es/weso/shex/ResolvedSchema.scala b/modules/shex/src/main/scala/es/weso/shex/ResolvedSchema.scala
index e170ae34..922302c5 100644
--- a/modules/shex/src/main/scala/es/weso/shex/ResolvedSchema.scala
+++ b/modules/shex/src/main/scala/es/weso/shex/ResolvedSchema.scala
@@ -22,6 +22,7 @@ case class ResolvedSchema(
resolvedMapShapeExprs: Map[ShapeLabel, ResolvedShapeExpr],
resolvedMapTripleExprs: Map[ShapeLabel, ResolvedTripleExpr],
inheritanceGraph: Inheritance[ShapeLabel, ShapesRelation],
+ // depGraph: DepGraph[ShapeLabel],
labelLocationMap: Option[Map[ShapeLabel, Location]]
) extends AbstractSchema {
diff --git a/modules/shex/src/main/scala/es/weso/shex/Schema.scala b/modules/shex/src/main/scala/es/weso/shex/Schema.scala
index 9074f664..d3bd5590 100644
--- a/modules/shex/src/main/scala/es/weso/shex/Schema.scala
+++ b/modules/shex/src/main/scala/es/weso/shex/Schema.scala
@@ -101,13 +101,13 @@ case class Schema(
def addTripleExprMap(te: Map[ShapeLabel, TripleExpr]): Schema =
this.copy(optTripleExprMap = Some(te))
- def oddNegCycles: Either[String, Set[Set[(ShapeLabel, ShapeLabel)]]] =
+ lazy val oddNegCycles: Either[String, Set[Set[(ShapeLabel, ShapeLabel)]]] =
Dependencies.oddNegCycles(this)
- def negCycles: Either[String, Set[Set[(ShapeLabel, ShapeLabel)]]] =
+ lazy val negCycles: Either[String, Set[Set[(ShapeLabel, ShapeLabel)]]] =
Dependencies.negCycles(this)
- def depGraph: Either[String, DepGraph[ShapeLabel]] =
+ lazy val depGraph: Either[String, DepGraph[ShapeLabel]] =
Dependencies.depGraph(this)
def showCycles(str: Either[String, Set[Set[(ShapeLabel, ShapeLabel)]]]): String = str match {
@@ -142,9 +142,9 @@ case class Schema(
lazy val wellFormed: Either[String, Unit] = for {
_ <- checkOddNegCycles
- // _ <- { println(s"Passed checkOddNegCycles..."); Right(())}
+ _ <- { println(s"Passed checkOddNegCycles..."); Right(()) }
_ <- checkBadShapeLabels
- // _ <- { println(s"Passed checkBadShapeLabels..."); Right(())}
+ _ <- { println(s"Passed checkBadShapeLabels..."); Right(()) }
} yield (())
def relativize(maybeBase: Option[IRI]): Schema = maybeBase match {
@@ -161,7 +161,7 @@ case class Schema(
def resolve(base: Option[IRI], verbose: VerboseLevel): IO[ResolvedSchema] =
ResolvedSchema.resolve(this, base, verbose)
- def withId(iri: IRI): Schema = this.copy(id = iri)
+ def withId(iri: IRI): Schema = this.copy(id = iri)
def withShapes(ses: ShapeExpr*): Schema = this.copy(shapes = ses.toList.some)
@@ -177,7 +177,6 @@ object Schema {
def emptyWithId(iri: IRI): Schema =
Schema.empty.withId(iri)
-
def fromIRI(
i: IRI,
base: Option[IRI],
diff --git a/project/build.properties b/project/build.properties
index fae470c0..4e2402af 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=1.8.0
+sbt.version=1.10.11
diff --git a/project/metals.sbt b/project/metals.sbt
index aaf3382f..ce00deb3 100644
--- a/project/metals.sbt
+++ b/project/metals.sbt
@@ -3,6 +3,6 @@
// This file enables sbt-bloop to create bloop config files.
-addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.17")
+addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "2.0.9")
// format: on
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 7c1ad868..ee9e611d 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,13 +1,13 @@
-addSbtPlugin("com.codecommit" % "sbt-github-actions" % "0.14.2")
-addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0")
+addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.25.0")
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.0")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
addSbtPlugin("com.github.sbt" % "sbt-unidoc" % "0.5.0")
-addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.10")
-// addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.0")
-addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.9")
+addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12")
+addSbtPlugin("com.github.sbt" % "sbt-git" % "2.1.0")
+addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.11.1")
addSbtPlugin("org.lyranthe.sbt" % "partial-unification" % "1.1.2")
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.5")
-addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.0")
+addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.3.1")
addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.3")
-addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.1")
+addSbtPlugin("com.github.sbt" % "sbt-site-asciidoctor" % "1.5.0")
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1")
diff --git a/project/project/metals.sbt b/project/project/metals.sbt
index aaf3382f..ce00deb3 100644
--- a/project/project/metals.sbt
+++ b/project/project/metals.sbt
@@ -3,6 +3,6 @@
// This file enables sbt-bloop to create bloop config files.
-addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.17")
+addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "2.0.9")
// format: on
diff --git a/project/project/project/metals.sbt b/project/project/project/metals.sbt
index aaf3382f..ce00deb3 100644
--- a/project/project/project/metals.sbt
+++ b/project/project/project/metals.sbt
@@ -3,6 +3,6 @@
// This file enables sbt-bloop to create bloop config files.
-addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.17")
+addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "2.0.9")
// format: on
diff --git a/src/main/scala/es/weso/shexs/Main.scala b/src/main/scala/es/weso/shexs/Main.scala
index ef1f1d57..1318c3b7 100644
--- a/src/main/scala/es/weso/shexs/Main.scala
+++ b/src/main/scala/es/weso/shexs/Main.scala
@@ -10,6 +10,8 @@ import es.weso.shex.validator.Validator
import es.weso.shextest.manifest.{Validate => _, _}
import com.monovore.decline._
import com.monovore.decline.effect._
+import com.typesafe.scalalogging.LazyLogging
+
// import buildinfo._
import java.nio.file.Path
import es.weso.shapepath.schemamappings.SchemaMappings
@@ -45,7 +47,8 @@ object Main
name = "shex-s",
header = "ShEx-Scala command line tool",
version = "0.2.2" // BuildInfo.version
- ) {
+ )
+ with LazyLogging {
lazy val mappingOpt = Opts.option[Path](
"mapping",
@@ -72,7 +75,31 @@ object Main
if (verbose) IO.println(msg)
else IO(())
- override def main: Opts[IO[ExitCode]] =
+ private def disable_logs(): Unit = {
+ // The following code is needed to remove extra logging from Jena
+ import org.apache.jena.riot.system.stream.JenaIOEnvironment
+ import org.apache.jena.riot.system.stream.LocationMapper
+ val mapper: LocationMapper = new LocationMapper()
+ JenaIOEnvironment.setGlobalLocationMapper(mapper)
+
+ // Force logging level to None
+ val log: ch.qos.logback.classic.Logger =
+ logger.underlying.asInstanceOf[ch.qos.logback.classic.Logger]
+ log.getName()
+ import org.slf4j.LoggerFactory
+ import ch.qos.logback.classic._
+ val es_weso_log: ch.qos.logback.classic.Logger =
+ LoggerFactory.getLogger("es.weso").asInstanceOf[ch.qos.logback.classic.Logger]
+ val org_log: ch.qos.logback.classic.Logger =
+ LoggerFactory.getLogger("org").asInstanceOf[ch.qos.logback.classic.Logger]
+ org_log.setLevel(Level.OFF)
+ es_weso_log.setLevel(Level.OFF)
+ log.setLevel(Level.OFF)
+
+ }
+
+ override def main: Opts[IO[ExitCode]] = {
+ disable_logs()
schemaMappingCommand
.orElse(Validate.validateCommand)
.orElse(shapePathValidateCommand)
@@ -90,6 +117,7 @@ object Main
.map(
_.handleErrorWith(infoError)
)
+ }
def infoError(err: Throwable): IO[ExitCode] =
IO.println(s"Error ${err.getLocalizedMessage()}") *> IO(ExitCode.Error)
diff --git a/src/main/scala/es/weso/shexs/SchemaCommand.scala b/src/main/scala/es/weso/shexs/SchemaCommand.scala
index 6b4fad18..2a066cdf 100644
--- a/src/main/scala/es/weso/shexs/SchemaCommand.scala
+++ b/src/main/scala/es/weso/shexs/SchemaCommand.scala
@@ -17,6 +17,7 @@ import io.circe._
import io.circe.syntax._
import es.weso.shex.Extends
import es.weso.shex.References
+import es.weso.shex.Schema
sealed abstract class ShowMethod {
val name: String
@@ -53,6 +54,7 @@ object ShowMethod {
case class SchemaCommand(
schemaSpec: SchemaSpec,
showInheritance: Boolean,
+ showDependencyGraph: Boolean,
showMethod: ShowMethod,
showShape: Option[ShapeLabel],
verbose: VerboseLevel
@@ -61,15 +63,29 @@ case class SchemaCommand(
schema <- schemaSpec.getSchema(verbose)
resolved <- ResolvedSchema.resolve(schema, schemaSpec.baseIRI, verbose)
_ <- showShapeLabels(resolved)
+ _ <- showWellFormed(schema)
_ <-
if (showInheritance) runShowInheritance(resolved)
else IO.pure(())
+ _ <-
+ if (showDependencyGraph) showDepGraph(resolved)
+ else IO.pure(())
_ <- showShape match {
case None => IO.pure(())
case Some(sl) => runShowShapeLabel(sl, resolved, showMethod)
}
} yield ExitCode.Success
+ private def showWellFormed(schema: Schema): IO[Unit] = {
+ val wellFormed = schema.wellFormed
+ wellFormed match {
+ case Left(msg) =>
+ IO.println(s"Schema is NOT well-formed: ${msg}")
+ case Right(_) =>
+ IO.println("Schema is well-formed")
+ }
+ }
+
private def showShapeLabels(schema: ResolvedSchema): IO[Unit] = {
val labels = schema.resolvedMapShapeExprs.keySet
IO.println(
@@ -77,6 +93,16 @@ case class SchemaCommand(
)
}
+ private def showDepGraph(schema: ResolvedSchema): IO[Unit] = {
+ val eitherDepGraph = schema.source.depGraph
+ eitherDepGraph match {
+ case Left(err) =>
+ IO.println(s"Error obtaining dependency graph: $err")
+ case Right(depGraph) =>
+ IO.println(s"Dependency graph:\n${depGraph.showEdges(lbl => schema.qualify(lbl.toRDFNode))}")
+ }
+ }
+
private def runShowInheritance(schema: ResolvedSchema): IO[Unit] = for {
inheritanceStr <-
schema.inheritanceGraph.show(lbl => schema.qualify(lbl.toRDFNode), r => s" -${r.name}-> ")
@@ -118,7 +144,9 @@ object SchemaCommand {
val showInheritance: Opts[Boolean] =
Opts.flag("show-inheritance", short = "i", help = "show inheritance graph").orFalse
-// val showMethod: Opts[ShowMethod] = Opts.option[String]("show-qualified", short = "q", help = "show shapes qualified by prefix declarations").orFalse
+
+ val showDependencyGraph: Opts[Boolean] =
+ Opts.flag("show-dependency-graph", short = "d", help = "show dependency graph").orFalse
val showShape: Opts[Option[ShapeLabel]] =
UriOpt.uri("shape", help = "Show shape").map(uri => IRILabel(IRI(uri))).orNone
@@ -128,6 +156,7 @@ object SchemaCommand {
(
SchemaSpec.schemaSpec,
showInheritance,
+ showDependencyGraph,
ShowMethod.showMethodOpt,
showShape,
VerboseLevelOpt.verboseLevel
diff --git a/version.sbt b/version.sbt
index 007e6b01..c5cd8d93 100644
--- a/version.sbt
+++ b/version.sbt
@@ -1 +1 @@
-ThisBuild / version := "0.2.33"
+ThisBuild / version := "0.2.34"