Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(ontology): Add support for additional ontologies (DEV-512) (#2029)
* update java version for docker base image

* allow external ontologies

* add test

* Update docstring

* add test

* add test

* add test for resource creation

* update test description

* add missing new line

* separate test into multiple parts

* add type annotations
  • Loading branch information
irinaschubert committed Apr 6, 2022
1 parent 00b5d55 commit 50e3186
Show file tree
Hide file tree
Showing 5 changed files with 400 additions and 9 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Expand Up @@ -171,7 +171,7 @@ lazy val webapi: Project = Project(id = "webapi", base = file("webapi"))
Docker / dockerRepository := Some("daschswiss"),
Docker / packageName := "knora-api",
dockerUpdateLatest := true,
dockerBaseImage := "eclipse-temurin:11-jre-focal",
dockerBaseImage := "eclipse-temurin:17-jre-focal",
Docker / maintainer := "support@dasch.swiss",
Docker / dockerExposedPorts ++= Seq(3333),
Docker / defaultLinuxInstallLocation := "/opt/docker",
Expand Down
23 changes: 23 additions & 0 deletions test_data/ontologies/freetest-onto.ttl
Expand Up @@ -148,6 +148,18 @@
rdfs:comment """A comment for FTRC."""@de .


:FreeTestSubClassOfFoafPerson
rdf:type owl:Class ;
rdfs:subClassOf foaf:Person,
knora-base:Resource,
[ rdf:type owl:Restriction ;
owl:onProperty :hasFoafName ;
owl:minCardinality "0"^^xsd:nonNegativeInteger ;
salsah-gui:guiOrder "1"^^xsd:nonNegativeInteger ] ;
rdfs:label "FTRCFoafPerson en"@en ;
rdfs:comment """A comment for FTRCFoafPerson."""@de .


:Author
rdf:type owl:Class ;
rdfs:subClassOf knora-base:Resource,
Expand Down Expand Up @@ -299,3 +311,14 @@
knora-base:objectClassConstraint
knora-base:TextValue ;
salsah-gui:guiElement salsah-gui:Richtext .

:hasFoafName
rdf:type owl:ObjectProperty ;
rdfs:subPropertyOf knora-base:hasValue,
foaf:name ;
rdfs:label "FoafName"@en ;
knora-base:subjectClassConstraint :FreeTestSubClassOfFoafPerson ;
knora-base:objectClassConstraint knora-base:TextValue ;
salsah-gui:guiElement salsah-gui:SimpleText ;
salsah-gui:guiAttribute "size=80",
"maxlength=255" .
Expand Up @@ -956,11 +956,15 @@ object OntologyHelpers {
directCardinalities = internalClassDef.directCardinalities ++ linkValuePropCardinalitiesToAdd
)

// Get the cardinalities that the class can inherit.
// Get the cardinalities that the class can inherit. If the ontology of the base class can't be found, it's assumed to be an external ontology (p.ex. foaf).

val cardinalitiesAvailableToInherit: Map[SmartIri, KnoraCardinalityInfo] =
classDefWithAddedLinkValueProps.subClassOf.flatMap { baseClassIri =>
cacheData.ontologies(baseClassIri.getOntologyFromEntity).classes(baseClassIri).allCardinalities
classDefWithAddedLinkValueProps.subClassOf.flatMap { baseClassIri: SmartIri =>
val ontology = cacheData.ontologies.getOrElse(baseClassIri.getOntologyFromEntity, None)
ontology match {
case ontology: ReadOntologyV2 => ontology.classes(baseClassIri).allCardinalities
case _ => None
}
}.toMap

// Check that the cardinalities directly defined on the class are compatible with any inheritable
Expand Down
Expand Up @@ -61,7 +61,11 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
override lazy val rdfDataObjects: List[RdfDataObject] = List(
RdfDataObject(path = "test_data/all_data/incunabula-data.ttl", name = "http://www.knora.org/data/0803/incunabula"),
RdfDataObject(path = "test_data/demo_data/images-demo-data.ttl", name = "http://www.knora.org/data/00FF/images"),
RdfDataObject(path = "test_data/all_data/anything-data.ttl", name = "http://www.knora.org/data/0001/anything")
RdfDataObject(path = "test_data/all_data/anything-data.ttl", name = "http://www.knora.org/data/0001/anything"),
RdfDataObject(
path = "test_data/ontologies/freetest-onto.ttl",
name = "http://www.knora.org/ontology/0001/freetest"
)
)

private val instanceChecker: InstanceChecker = InstanceChecker.getJsonLDChecker
Expand Down Expand Up @@ -181,7 +185,11 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
val responseAsString = responseToString(response)
assert(response.status == StatusCodes.OK, responseAsString)
val expectedAnswerJSONLD =
readOrWriteTextFile(responseAsString, Paths.get("..", "test_data/resourcesR2RV2/AThing.jsonld"), writeTestDataFiles)
readOrWriteTextFile(
responseAsString,
Paths.get("..", "test_data/resourcesR2RV2/AThing.jsonld"),
writeTestDataFiles
)
compareJSONLDForResourcesResponse(expectedJSONLD = expectedAnswerJSONLD, receivedJSONLD = responseAsString)

clientTestDataCollector.addFile(
Expand Down Expand Up @@ -476,7 +484,11 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
val responseAsString = responseToString(response)
assert(response.status == StatusCodes.OK, responseAsString)
val expectedAnswerJSONLD =
readOrWriteTextFile(responseAsString, Paths.get("..", "test_data/resourcesR2RV2/Testding.jsonld"), writeTestDataFiles)
readOrWriteTextFile(
responseAsString,
Paths.get("..", "test_data/resourcesR2RV2/Testding.jsonld"),
writeTestDataFiles
)
compareJSONLDForResourcesResponse(expectedJSONLD = expectedAnswerJSONLD, receivedJSONLD = responseAsString)

clientTestDataCollector.addFile(
Expand Down Expand Up @@ -1008,6 +1020,74 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
assert(text == "this is text with standoff")
}

"create a resource and a property with references to an external ontology (FOAF)" in {
val createResourceWithRefToFoaf: String =
"""{
| "@type" : "freetest:FreeTestSubClassOfFoafPerson",
| "freetest:hasFoafName" : {
| "@type" : "knora-api:TextValue",
| "knora-api:valueAsString" : "this is a foaf name"
| },
| "knora-api:attachedToProject" : {
| "@id" : "http://rdfh.ch/projects/0001"
| },
| "rdfs:label" : "Test foaf Person",
| "@context" : {
| "rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
| "knora-api" : "http://api.knora.org/ontology/knora-api/v2#",
| "rdfs" : "http://www.w3.org/2000/01/rdf-schema#",
| "xsd" : "http://www.w3.org/2001/XMLSchema#",
| "freetest" : "http://0.0.0.0:3333/ontology/0001/freetest/v2#"
| }
|}""".stripMargin

val request = Post(
s"$baseApiUrl/v2/resources",
HttpEntity(RdfMediaTypes.`application/ld+json`, createResourceWithRefToFoaf)
) ~> addCredentials(BasicHttpCredentials(anythingUserEmail, password))
val response: HttpResponse = singleAwaitingRequest(request)
assert(response.status == StatusCodes.OK, response.toString)
val responseJsonDoc: JsonLDDocument = responseToJsonLDDocument(response)
val resourceIri: IRI =
responseJsonDoc.body.requireStringWithValidation(JsonLDKeywords.ID, stringFormatter.validateAndEscapeIri)
assert(resourceIri.toSmartIri.isKnoraDataIri)

// Request the newly created resource in the complex schema, and check that it matches the ontology.
val resourceComplexGetRequest = Get(
s"$baseApiUrl/v2/resources/${URLEncoder.encode(resourceIri, "UTF-8")}"
) ~> addCredentials(BasicHttpCredentials(anythingUserEmail, password))
val resourceComplexGetResponse: HttpResponse = singleAwaitingRequest(resourceComplexGetRequest)
val resourceComplexGetResponseAsString = responseToString(resourceComplexGetResponse)

instanceChecker.check(
instanceResponse = resourceComplexGetResponseAsString,
expectedClassIri = "http://0.0.0.0:3333/ontology/0001/freetest/v2#FreeTestSubClassOfFoafPerson".toSmartIri,
knoraRouteGet = doGetRequest
)

// Request the newly created resource in the simple schema, and check that it matches the ontology.
val resourceSimpleGetRequest = Get(s"$baseApiUrl/v2/resources/${URLEncoder.encode(resourceIri, "UTF-8")}")
.addHeader(new SchemaHeader(RouteUtilV2.SIMPLE_SCHEMA_NAME)) ~> addCredentials(
BasicHttpCredentials(anythingUserEmail, password)
)
val resourceSimpleGetResponse: HttpResponse = singleAwaitingRequest(resourceSimpleGetRequest)
val resourceSimpleGetResponseAsString = responseToString(resourceSimpleGetResponse)

instanceChecker.check(
instanceResponse = resourceSimpleGetResponseAsString,
expectedClassIri =
"http://0.0.0.0:3333/ontology/0001/freetest/simple/v2#FreeTestSubClassOfFoafPerson".toSmartIri,
knoraRouteGet = doGetRequest
)

// Check that the value is correct in the simple schema.
val resourceSimpleAsJsonLD: JsonLDDocument = JsonLDUtil.parseJsonLD(resourceSimpleGetResponseAsString)
println(resourceSimpleAsJsonLD.body)
val foafName: String =
resourceSimpleAsJsonLD.body.requireString("http://0.0.0.0:3333/ontology/0001/freetest/simple/v2#hasFoafName")
assert(foafName == "this is a foaf name")
}

"create a resource whose label contains a Unicode escape and quotation marks" in {
val jsonLDEntity: String =
FileUtil.readTextFile(Paths.get("..", "test_data/resourcesR2RV2/ThingWithUnicodeEscape.jsonld"))
Expand Down Expand Up @@ -1566,7 +1646,8 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
}

"create a resource containing escaped text" in {
val jsonLDEntity = FileUtil.readTextFile(Paths.get("..", "test_data/resourcesR2RV2/CreateResourceWithEscape.jsonld"))
val jsonLDEntity =
FileUtil.readTextFile(Paths.get("..", "test_data/resourcesR2RV2/CreateResourceWithEscape.jsonld"))
val request = Post(
s"$baseApiUrl/v2/resources",
HttpEntity(RdfMediaTypes.`application/ld+json`, jsonLDEntity)
Expand Down Expand Up @@ -2205,7 +2286,11 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
val responseJson: JsValue = JsonParser(responseStr)

val expectedJson: JsValue = JsonParser(
readOrWriteTextFile(responseStr, Paths.get("..", "test_data/resourcesR2RV2/IIIFManifest.jsonld"), writeTestDataFiles)
readOrWriteTextFile(
responseStr,
Paths.get("..", "test_data/resourcesR2RV2/IIIFManifest.jsonld"),
writeTestDataFiles
)
)

assert(responseJson == expectedJson)
Expand Down

0 comments on commit 50e3186

Please sign in to comment.