Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
feat(rdf-api): Add a general-purpose SHACL validation utility (DSP-93…
…0) (#1762)
- Loading branch information
Benjamin Geer
committed
Dec 1, 2020
1 parent
346873d
commit bfd3192
Showing
31 changed files
with
848 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
@prefix ex: <http://example.com/ns#> . | ||
@prefix sh: <http://www.w3.org/ns/shacl#> . | ||
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . | ||
@prefix foaf: <http://xmlns.com/foaf/0.1/> . | ||
|
||
ex:PersonShape a sh:NodeShape ; | ||
sh:targetClass foaf:Person ; | ||
sh:property ex:PersonShapeProperty . | ||
|
||
ex:PersonShapeProperty sh:path foaf:age ; | ||
sh:datatype xsd:int ; | ||
sh:maxCount 1 ; | ||
sh:minCount 1 . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
webapi/src/main/scala/org/knora/webapi/messages/util/rdf/AbstractShaclValidator.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* Copyright © 2015-2019 the contributors (see Contributors.md). | ||
* | ||
* This file is part of Knora. | ||
* | ||
* Knora is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published | ||
* by the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* Knora is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public | ||
* License along with Knora. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package org.knora.webapi.messages.util.rdf | ||
|
||
import java.nio.file.attribute.BasicFileAttributes | ||
import java.nio.file._ | ||
|
||
import org.knora.webapi.exceptions.AssertionException | ||
|
||
/** | ||
* An abstract base class for classes that validate RDF models using SHACL shapes. | ||
* | ||
* @param baseDir the base directory that SHACL graphs are loaded from. | ||
* @param rdfFormatUtil an [[RdfFormatUtil]]. | ||
* @tparam ShaclGraphT an implementation-specific representation of a graph of SHACL shapes. | ||
*/ | ||
abstract class AbstractShaclValidator[ShaclGraphT](baseDir: Path, private val rdfFormatUtil: RdfFormatUtil) extends ShaclValidator { | ||
|
||
/** | ||
* A map of relative paths to objects representing graphs of SHACL shapes. | ||
*/ | ||
private val shaclGraphs: Map[Path, ShaclGraphT] = if (Files.exists(baseDir)) { | ||
val fileVisitor = new ShaclGraphCollectingFileVisitor | ||
Files.walkFileTree(baseDir, fileVisitor) | ||
fileVisitor.visitedShaclGraphs.toMap | ||
} else { | ||
Map.empty | ||
} | ||
|
||
def validate(rdfModel: RdfModel, shaclPath: Path): ShaclValidationResult = { | ||
validateWithShaclGraph( | ||
rdfModel = rdfModel, | ||
shaclGraph = shaclGraphs.getOrElse(shaclPath, throw AssertionException(s"SHACL graph $shaclPath not found")) | ||
) | ||
} | ||
|
||
/** | ||
* A [[FileVisitor]] that loads graphs of SHACL shapes while walking a file tree. | ||
*/ | ||
private class ShaclGraphCollectingFileVisitor extends SimpleFileVisitor[Path] { | ||
// A collection of the graphs that have been loaded so far. | ||
val visitedShaclGraphs: collection.mutable.Map[Path, ShaclGraphT] = collection.mutable.Map.empty | ||
|
||
override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = { | ||
// Is this a Turtle file? | ||
if (file.getFileName.toString.endsWith(".ttl")) { | ||
// Yes. Parse it. | ||
val shaclModel: RdfModel = rdfFormatUtil.fileToRdfModel(file = file.toFile, rdfFormat = Turtle) | ||
|
||
// Convert it to a ShaclGraphT. | ||
val shaclGraph: ShaclGraphT = rdfModelToShaclGraph(shaclModel) | ||
|
||
// Get its path relative to baseDir. | ||
val relativePath: Path = baseDir.relativize(file) | ||
|
||
// Add it to the collection. | ||
visitedShaclGraphs += relativePath -> shaclGraph | ||
} | ||
|
||
FileVisitResult.CONTINUE | ||
} | ||
} | ||
|
||
/** | ||
* Validates the default graph of an [[RdfModel]] using a graph of SHACL shapes. | ||
* | ||
* @param rdfModel the [[RdfModel]] to be validated. | ||
* @param shaclGraph a graph of SHACL shapes. | ||
* @return the validation result. | ||
*/ | ||
protected def validateWithShaclGraph(rdfModel: RdfModel, shaclGraph: ShaclGraphT): ShaclValidationResult | ||
|
||
/** | ||
* Converts the default graph of an [[RdfModel]] to a [[ShaclGraphT]]. | ||
* | ||
* @param rdfModel an [[RdfModel]] whose default graph contains SHACL shapes. | ||
* @return a [[ShaclGraphT]] representing the SHACL shapes. | ||
*/ | ||
protected def rdfModelToShaclGraph(rdfModel: RdfModel): ShaclGraphT | ||
} |
Oops, something went wrong.