Skip to content

Commit

Permalink
Follow subClassOf when including ontologies in XML import schemas (#991)
Browse files Browse the repository at this point in the history
* fix (ResourcesRouteV1): Follow subClassOf when including ontologies in XML import schemas.

* docs: Update release notes.

* test (ResourcesResponderV1): Fix test.
  • Loading branch information
Benjamin Geer authored Sep 11, 2018
1 parent 392636f commit dce986f
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/src/paradox/00-release-notes/v1.8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ See the
- update sbt to 1.2.1 (@github[#979](#979))
- remove Kamon monitoring (for now) since we don't see anything meaningful there. We probably will have to instrument Knora by hand and then use Kamon for access. (@github[#979](#979))
- update Dockerfiles for `webapi` and `salsah1` (@github[#979](#979))
- Follow subClassOf when including ontologies in XML import schemas (@github[#991](#991))

## Bugfixes:

Expand Down
14 changes: 14 additions & 0 deletions webapi/_test_data/ontologies/anything-onto.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,20 @@
rdfs:comment """Diese Resource-Klasse beschreibt ein Bild eines Dinges"""@de .


:TrivialThing rdf:type owl:Class ;

rdfs:subClassOf knora-base:Resource ;

knora-base:resourceIcon "thing.png" ;

rdfs:label "Unbedeutendes Ding"@de ,
"Chose sans importance"@fr ,
"Cosa senza importanza"@it ,
"Trivial thing"@en ;

rdfs:comment """Diese Resource-Klasse beschreibt ein unbedeutendes Ding"""@de .


#################################################################
#
# Standoff Classes
Expand Down
32 changes: 32 additions & 0 deletions webapi/_test_data/ontologies/empty-thing-onto.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix knora-base: <http://www.knora.org/ontology/knora-base#> .
@prefix salsah-gui: <http://www.knora.org/ontology/salsah-gui#> .

@prefix anything: <http://www.knora.org/ontology/0001/anything#> .

@base <http://www.knora.org/ontology/0001/empty-thing> .

# A trivial ontology, based on anything-onto.ttl, used only for testing Knora.

@prefix : <http://www.knora.org/ontology/0001/empty-thing#> .
<http://www.knora.org/ontology/0001/empty-thing> rdf:type owl:Ontology ;
rdfs:label "The empty thing ontology" ;
knora-base:attachedToProject <http://rdfh.ch/projects/0001> .

:EmptyThing rdf:type owl:Class ;

rdfs:subClassOf anything:TrivialThing ;

knora-base:resourceIcon "thing.png" ;

rdfs:label "Leeres Ding"@de ,
"Chose vide"@fr ,
"Cosa vuota"@it ,
"Empty thing"@en ;

rdfs:comment """An empty thing."""@en .
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ class ClassInfoV1(classInfoV2: ReadClassInfoV2) extends EntityInfoV1 {
*/
def resourceClassIri: IRI = classInfoV2.entityInfoContent.classIri.toString

/**
* Returns the IRIs of all the base classes of the resource class.
*/
def subClassOf: Set[IRI] = classInfoV2.entityInfoContent.subClassOf.map(_.toString)

def allCardinalities: Map[IRI, KnoraCardinalityInfo] = {
classInfoV2.allCardinalities.map {
case (smartIri, cardinality) => smartIri.toString -> cardinality
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,15 @@ object ResourcesRouteV1 extends Authenticator {
userProfile = userProfile
)).mapTo[EntityInfoGetResponseV1]

// Look at the base classes of all the resource classes in the initial ontology. Make a set of
// the ontologies containing the definitions of those classes, not including including the initial ontology itself
// or any other ontologies we've already looked at.
ontologyIrisFromBaseClasses: Set[IRI] = entityInfoResponse.resourceClassInfoMap.foldLeft(Set.empty[IRI]) {
case (acc, (resourceClassIri, resourceClassInfo)) =>
val subClassOfOntologies: Set[IRI] = resourceClassInfo.subClassOf.map(_.toSmartIri).filter(_.isKnoraDefinitionIri).map(_.getOntologyFromEntity.toString)
acc ++ subClassOfOntologies
} -- intermediateResults.keySet - initialOntologyIri

// Look at the properties that have cardinalities in the resource classes in the initial ontology.
// Make a set of the ontologies containing the definitions of those properties, not including the initial ontology itself
// or any other ontologies we've already looked at.
Expand All @@ -405,7 +414,7 @@ object ResourcesRouteV1 extends Authenticator {
}.toSet -- intermediateResults.keySet - initialOntologyIri

// Make a set of all the ontologies referenced by the initial ontology.
referencedOntologies: Set[IRI] = ontologyIrisFromCardinalities ++ ontologyIrisFromObjectClassConstraints
referencedOntologies: Set[IRI] = ontologyIrisFromBaseClasses ++ ontologyIrisFromCardinalities ++ ontologyIrisFromObjectClassConstraints

// Recursively get NamedGraphEntityInfoV1 instances for each of those ontologies.
lastResults: Map[IRI, NamedGraphEntityInfoV1] <- referencedOntologies.foldLeft(FastFuture.successful(intermediateResults + (initialOntologyIri -> initialNamedGraphInfo))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class ResourcesV1R2RSpec extends R2RSpec {
implicit val ec: ExecutionContextExecutor = system.dispatcher

override lazy val rdfDataObjects = List(
RdfDataObject(path = "_test_data/ontologies/empty-thing-onto.ttl", name = "http://www.knora.org/ontology/0001/empty-thing"),
RdfDataObject(path = "_test_data/all_data/anything-data.ttl", name = "http://www.knora.org/data/0001/anything"),
RdfDataObject(path = "_test_data/demo_data/images-demo-data.ttl", name = "http://www.knora.org/data/00FF/images"),
RdfDataObject(path = "_test_data/all_data/incunabula-data.ttl", name = "http://www.knora.org/data/0803/incunabula")
Expand Down Expand Up @@ -1506,6 +1507,29 @@ class ResourcesV1R2RSpec extends R2RSpec {
}
}

"follow rdfs:subClassOf when generating XML schemas for referenced ontologies in an XML import" in {
val ontologyIri = URLEncoder.encode("http://www.knora.org/ontology/0001/empty-thing", "UTF-8")

Get(s"/v1/resources/xmlimportschemas/$ontologyIri") ~> addCredentials(BasicHttpCredentials(beolUserEmail, password)) ~> resourcesPath ~> check {
val responseBodyFuture: Future[Array[Byte]] = response.entity.toStrict(5.seconds).map(_.data.toArray)
val responseBytes: Array[Byte] = Await.result(responseBodyFuture, 5.seconds)
val zippedFilenames = collection.mutable.Set.empty[String]

for (zipInputStream <- managed(new ZipInputStream(new ByteArrayInputStream(responseBytes)))) {
var zipEntry: ZipEntry = null

while ( {
zipEntry = zipInputStream.getNextEntry
zipEntry != null
}) {
zippedFilenames.add(zipEntry.getName)
}
}

assert(zippedFilenames == Set("p0001-empty-thing.xsd", "knoraXmlImport.xsd", "p0001-anything.xsd"))
}
}

"create 10,000 anything:Thing resources with random contents" in {
def maybeAppendValue(random: Random, xmlStringBuilder: StringBuilder, value: String): Unit = {
if (random.nextBoolean) {
Expand Down

0 comments on commit dce986f

Please sign in to comment.