New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(api-v2): Add an RDF processing façade (DSP-1020) #1754
Conversation
graphContents match { | ||
case jsonLDArray: JsonLDArray => | ||
// Add each of the array's elements to the model. | ||
for (elem <- jsonLDArray.value) { | ||
elem match { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment here: like "Is the element a JSON-LD Object? Yes. Add to the model. No. Invalid graph "
*/ | ||
object JsonLDConstants { | ||
object JsonLDKeywords { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am so glad you renamed this.
|
||
case jsonLDArray: JsonLDArray => | ||
// It has more than one @type. | ||
// More than one. | ||
for (elem <- jsonLDArray.value) { | ||
elem match { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment here like: "Is each element of @type string?" Yes. Add the type to the model. No. Throw exception.
val thisModelNamedGraphIris: Set[jena.graph.Node] = datasetGraph.listGraphNodes.asScala.toSet | ||
val thatModelNamedGraphIris: Set[jena.graph.Node] = thatDatasetGraph.listGraphNodes.asScala.toSet | ||
|
||
// The two models are isomorphic if: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! without this explanation, I wouldn't have got this part.
val graph1LabelStatement = nodeFactory.makeStatement( | ||
subj = nodeFactory.makeIriNode("http://example.org/6"), | ||
pred = labelPred, | ||
obj = nodeFactory.makeDatatypeLiteral(value = "Lucky's Discount X-Wing Repair", datatype = OntologyConstants.Xsd.String), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-D
val graph2LabelStatement = nodeFactory.makeStatement( | ||
subj = nodeFactory.makeIriNode("http://example.org/7"), | ||
pred = labelPred, | ||
obj = nodeFactory.makeDatatypeLiteral(value = "Mos Eisley Used Droids", datatype = OntologyConstants.Xsd.String), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Mos Eisley used droids that were not allowed in the Cantina"
|
||
// Compare that with the model generated by the JsonLDDocument. | ||
jsonLDOutputModel should ===(jsonLDExpectedModel) | ||
} | ||
|
||
"correctly convert an RDF model to JSON-LD if it contains a circular reference" in { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent!
@benjamingeer This looks great, thanks for all your work. |
Many thanks for reviewing this! |
This PR adds an RDF processing façade in
webapi/src/main/scala/org/knora/webapi/messages/util/rdf
, with two different implementations (Jena and RDF4J).The API
RdfModel
, which represents a set of RDF graphs (a default graph and/or one or more named graphs)RdfNode
and its subclasses, which represent RDF nodes (IRIs, blank nodes, and literals)Statement
, which represents a triple or quadRdfNodeFactory
, which creates nodes and statementsRdfModelFactory
, which creates empty RDF modelsRdfFormatUtil
, which parses and formats RDFRdfFeatureFactory
, which returns instances ofRdfNodeFactory
,RdfModelFactory
, andRdfFormatUtil
, using feature toggle configuration.The implementations
org.knora.webapi.messages.util.rdf.jenaimpl
org.knora.webapi.messages.util.rdf.rdf4jimpl
The feature toggle
jena-rdf-library
:on
means use the Jena implementationoff
(the default) means use the RDF4J implementation, which was previously the main one used in KnoraTasks
RdfModel
,RdfModelFactory
,RdfNodeFactory
).RdfFeatureFactory
).RdfFormatUtil
).JsonLDUtil
RouteUtilV2
KnoraRequestV2
KnoraResponseV2
HttpTriplestoreConnector
:SparqlConstructRequest
SparqlExtendedConstructRequest
featureFactoryConfig
to everything that depends onCONSTRUCT
requests (most of the changes in this PR)RDF4JModelSpec
RDF4JFormatUtilSpec
JsonLDUtilSpec
KnoraResponseV2Spec
E2ESpec
and subclasses.R2RSpec
and subclasses.MetadataMessagesV2Spec
MetadataRouteV2E2ESpec
What still uses RDF4J directly
ProjectsResponderADM.projectDataGetRequestADM
HttpTriplestoreConnector.turtleToTrig
RepositoryUpdater
TEIHeader
: uses XSLT that depends on the exact format of RDF/XML generated by RDF4J. The XSLT would need to be improved to handlerdf:Description
.GravsearchParser
: uses RDF4J's SPARQL parser, not worth changingTODO in a later PR