From f183d7d5d7c8bc5387a671dc9c589b55f42a44fb Mon Sep 17 00:00:00 2001 From: irinaschubert Date: Tue, 23 Aug 2022 11:50:39 +0200 Subject: [PATCH] fix(cardinality): Check cardinality with multiple inherited classes (DEV-1189) (#2164) * check that always the stricter cardinality is taken * add unit tests * remove replaced method * add comments * introduce value objects for cardinalities * check cardinality compatibility in case of multiple super classes * fix error message * clean up docstrings * fix broken docs link * remove unused project * fix error in docs * add testdata and tests * fix build.sbt * simplify test data * improve comments * cleanup imports * fix bad references for coverage * improve comments * reintroduce return * wrap case objects * simplify test * fix missing import * implement feedback from review * run scalafmt Co-authored-by: Ivan Subotic <400790+subotic@users.noreply.github.com> --- Makefile | 1 - build.sbt | 25 ++-- docs/02-knora-ontologies/knora-base.md | 2 +- docs/Readme.md | 2 +- .../scala/dsp/role/handler/RoleHandler.scala | 3 +- .../dsp/role/repo/impl/RoleRepoLive.scala | 3 +- .../dsp/role/repo/impl/RoleRepoMock.scala | 3 +- .../dsp/schema/domain/SchemaDomain.scala | 68 +++++++++ .../domain/SchemaFunctionalDomain.scala | 6 +- .../dsp/schema/handler/CreateSchema.scala | 4 +- .../scala/dsp/schema/repo/SchemaRepo.scala | 1 - .../schema/domain/SchemaCommandsSpec.scala | 2 +- test_data/ontologies/freetest-onto.ttl | 51 +++++++ .../webapi/messages/util/MessageUtil.scala | 19 +-- .../util/standoff/StandoffTagUtilV2.scala | 11 +- .../ontologymessages/OntologyMessagesV1.scala | 6 +- ...aseToApiV2ComplexTransformationRules.scala | 111 +++++++------- ...BaseToApiV2SimpleTransformationRules.scala | 11 +- .../ontologymessages/OntologyMessagesV2.scala | 82 +++-------- .../OntologyTransformationRules.scala | 2 +- .../responders/v1/OntologyResponderV1.scala | 11 +- .../responders/v1/ResourcesResponderV1.scala | 24 ++-- .../responders/v1/ValuesResponderV1.scala | 9 +- .../responders/v2/OntologyResponderV2.scala | 11 +- .../responders/v2/ResourcesResponderV2.scala | 10 +- .../responders/v2/StandoffResponderV2.scala | 9 +- .../responders/v2/ValuesResponderV2.scala | 24 ++-- .../webapi/responders/v2/ontology/Cache.scala | 2 +- ...alities.scala => CardinalityHandler.scala} | 15 +- .../v2/ontology/OntologyHelpers.scala | 78 +++++++--- .../v2/addCardinalitiesToClass.scala.txt | 4 +- .../queries/sparql/v2/createClass.scala.txt | 4 +- .../v2/replaceClassCardinalities.scala.txt | 4 +- .../messages/twirl/xsd/v1/xmlImport.scala.xml | 118 +++++---------- .../knora/webapi/e2e/InstanceChecker.scala | 8 +- .../webapi/e2e/v2/OntologyV2R2RSpec.scala | 7 +- .../InputOntologyV2Spec.scala | 7 +- ...raCardinalityInfoIsStricterThanZSpec.scala | 82 +++++++++++ .../v2/OntologyResponderV2Spec.scala | 136 +++++++++--------- .../AddCardinalitiesToClassSpec.scala | 6 +- .../DeleteCardinalitiesFromClassSpec.scala | 11 +- .../v2/ontology/OntologyHelpersSpec.scala | 85 +++++++++++ .../cache/impl/CacheInMemImplZSpec.scala | 6 +- .../cache/impl/CacheRedisImplZSpec.scala | 4 +- .../CacheSerializationZSpec.scala | 4 +- .../util/Base64UrlCheckDigitZSpec.scala | 6 +- 46 files changed, 672 insertions(+), 426 deletions(-) create mode 100644 dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaDomain.scala rename webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/{Cardinalities.scala => CardinalityHandler.scala} (98%) create mode 100644 webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraCardinalityInfoIsStricterThanZSpec.scala create mode 100644 webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpersSpec.scala diff --git a/Makefile b/Makefile index e6b9ed7af2..858b744715 100644 --- a/Makefile +++ b/Makefile @@ -209,7 +209,6 @@ test: build ## runs all tests sbt -v coverage "userHandler/test" sbt -v coverage "userInterface/test" sbt -v coverage "userRepo/test" - sbt -v coverage "valueObjects/test" sbt -v coverage "webapi/test" sbt coverageAggregate diff --git a/build.sbt b/build.sbt index 590e4d2f03..eb001ce128 100644 --- a/build.sbt +++ b/build.sbt @@ -27,7 +27,20 @@ lazy val buildSettings = Seq( lazy val rootBaseDir = ThisBuild / baseDirectory lazy val root: Project = Project(id = "root", file(".")) - .aggregate(webapi, sipi, shared, valueObjects, userCore, userHandler, userRepo, userInterface) + .aggregate( + webapi, + sipi, + shared, + userCore, + userHandler, + userRepo, + userInterface, + roleCore, + roleRepo, + roleHandler, + roleInterface, + schemaCore + ) .enablePlugins(GitVersioning, GitBranchPrompt) .settings( // values set for all sub-projects @@ -231,16 +244,6 @@ lazy val webapiJavaTestOptions = Seq( // DSP's new codebase ////////////////////////////////////// -// Value Objects project - -lazy val valueObjects = project - .in(file("dsp-value-objects")) - .settings( - name := "valueObjects", - libraryDependencies ++= Dependencies.valueObjectsLibraryDependencies, - testFrameworks := Seq(new TestFramework("zio.test.sbt.ZTestFramework")) - ) - // Role projects lazy val roleInterface = project diff --git a/docs/02-knora-ontologies/knora-base.md b/docs/02-knora-ontologies/knora-base.md index 2fb6104597..c203369941 100644 --- a/docs/02-knora-ontologies/knora-base.md +++ b/docs/02-knora-ontologies/knora-base.md @@ -32,7 +32,7 @@ In Knora, each item of data belongs to some particular project. Each project usi - `projectShortname` (1): A short name that can be used to identify the project in configuration files and the like. -- `projectLongname` (1): The full name of the project. +- `projectLongname` (0-1): The full name of the project. - `projectShortcode` (1): A hexadecimal code that uniquely identifies the project. These codes are assigned to projects by the [DaSCH](http://dasch.swiss/). diff --git a/docs/Readme.md b/docs/Readme.md index 2d9e3df4e8..8f79349761 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -3,7 +3,7 @@ ## MkDocs Documentation This folder contains the sources to the DSP-API documentation website published -under +under The `src` folder contains the following documentation sources: diff --git a/dsp-role/handler/src/main/scala/dsp/role/handler/RoleHandler.scala b/dsp-role/handler/src/main/scala/dsp/role/handler/RoleHandler.scala index 981c24f794..f1f1b55b1b 100644 --- a/dsp-role/handler/src/main/scala/dsp/role/handler/RoleHandler.scala +++ b/dsp-role/handler/src/main/scala/dsp/role/handler/RoleHandler.scala @@ -138,11 +138,10 @@ final case class RoleHandler(repo: RoleRepo) { * Companion object providing the layer with an initialized implementation */ object RoleHandler { - val layer: ZLayer[RoleRepo, Nothing, RoleHandler] = { + val layer: ZLayer[RoleRepo, Nothing, RoleHandler] = ZLayer { for { repo <- ZIO.service[RoleRepo] } yield RoleHandler(repo) }.tap(_ => ZIO.logInfo(">>> Role Handler initilaized <<<")) - } } diff --git a/dsp-role/repo/src/main/scala/dsp/role/repo/impl/RoleRepoLive.scala b/dsp-role/repo/src/main/scala/dsp/role/repo/impl/RoleRepoLive.scala index b325faa455..8ec834edc6 100644 --- a/dsp-role/repo/src/main/scala/dsp/role/repo/impl/RoleRepoLive.scala +++ b/dsp-role/repo/src/main/scala/dsp/role/repo/impl/RoleRepoLive.scala @@ -63,11 +63,10 @@ final case class RoleRepoLive( * Companion object providing the layer with an initialized implementation of [[RoleRepo]] */ object RoleRepoLive { - val layer: ZLayer[Any, Nothing, RoleRepo] = { + val layer: ZLayer[Any, Nothing, RoleRepo] = ZLayer { for { roles <- TMap.empty[UUID, Role].commit } yield RoleRepoLive(roles) }.tap(_ => ZIO.logInfo(">>> Role repository initialized <<<")) - } } diff --git a/dsp-role/repo/src/test/scala/dsp/role/repo/impl/RoleRepoMock.scala b/dsp-role/repo/src/test/scala/dsp/role/repo/impl/RoleRepoMock.scala index a814717551..a2ec357497 100644 --- a/dsp-role/repo/src/test/scala/dsp/role/repo/impl/RoleRepoMock.scala +++ b/dsp-role/repo/src/test/scala/dsp/role/repo/impl/RoleRepoMock.scala @@ -63,11 +63,10 @@ final case class RoleRepoMock( * Companion object providing the layer with an initialized implementation of [[RoleRepo]] */ object RoleRepoMock { - val layer: ZLayer[Any, Nothing, RoleRepo] = { + val layer: ZLayer[Any, Nothing, RoleRepo] = ZLayer { for { roles <- TMap.empty[UUID, Role].commit } yield RoleRepoMock(roles) }.tap(_ => ZIO.logInfo(">>> In-memory role repository initialized <<<")) - } } diff --git a/dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaDomain.scala b/dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaDomain.scala new file mode 100644 index 0000000000..ed767a2e30 --- /dev/null +++ b/dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaDomain.scala @@ -0,0 +1,68 @@ +/* + * Copyright © 2021 - 2022 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package dsp.schema.domain + +import Cardinality._ + +/** + * Represents a cardinality value object. + */ +sealed trait Cardinality { self => + + /** + * The string representation of the cardinality + */ + val value: String + + /** + * Checks whether a cardinality is stricter than another one. + * + * @param that the cardinality to be compared against + * @return `true` if the present cardinality is stricter than `that`, `false` otherwise + */ + def isStricterThan(that: Cardinality): Boolean = + if (self == that) { + false + } else { + self match { + case MustHaveOne => true + case MustHaveSome => that == MayHaveMany + case MayHaveOne => that == MayHaveMany + case MayHaveMany => false + } + } +} + +object Cardinality { + + /** + * The cardinality of a property that must have one value. + */ + final case object MustHaveOne extends Cardinality { + override val value: String = "1" + } + + /** + * The cardinality of a property that must have at least one value. + */ + final case object MustHaveSome extends Cardinality { + override val value: String = "1-n" + } + + /** + * The cardinality of a property that may have one value. + */ + final case object MayHaveOne extends Cardinality { + override val value: String = "0-1" + } + + /** + * The cardinality of a property that may have one or more values. + */ + final case object MayHaveMany extends Cardinality { + override val value: String = "0-n" + } +} diff --git a/dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaFunctionalDomain.scala b/dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaFunctionalDomain.scala index 25108a13cb..ed2966570c 100644 --- a/dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaFunctionalDomain.scala +++ b/dsp-schema/core/src/main/scala/dsp/schema/domain/SchemaFunctionalDomain.scala @@ -210,7 +210,7 @@ object SchemaDomain extends App { implicit def isSubtypeOf2[A, B >: A]: NotSubtypeOf[A, B] = new NotSubtypeOf[A, B] {} } - //trying it out + // trying it out val ontoInfo = OntologyInfo("test", "http://example.org/test", "Test", "Test") val classOne = OntologyClass("ClassOne", "Class One", "Class One") @@ -230,8 +230,8 @@ object SchemaDomain extends App { .withClass(classOne) .withClass(classTwo) .withProperty(propertyOne) - //.withProperty(propertyOne) - //.withProperty(propertyTwo) + // .withProperty(propertyOne) + // .withProperty(propertyTwo) .withCardinality(cardOne) .withCardinality(cardOne) diff --git a/dsp-schema/core/src/main/scala/dsp/schema/handler/CreateSchema.scala b/dsp-schema/core/src/main/scala/dsp/schema/handler/CreateSchema.scala index b0cb24b05a..da58387d44 100644 --- a/dsp-schema/core/src/main/scala/dsp/schema/handler/CreateSchema.scala +++ b/dsp-schema/core/src/main/scala/dsp/schema/handler/CreateSchema.scala @@ -1,5 +1,3 @@ package dsp.schema.handler -object CreateSchema { - -} +object CreateSchema {} diff --git a/dsp-schema/core/src/main/scala/dsp/schema/repo/SchemaRepo.scala b/dsp-schema/core/src/main/scala/dsp/schema/repo/SchemaRepo.scala index 00983c9cee..4d4bb5121b 100644 --- a/dsp-schema/core/src/main/scala/dsp/schema/repo/SchemaRepo.scala +++ b/dsp-schema/core/src/main/scala/dsp/schema/repo/SchemaRepo.scala @@ -3,7 +3,6 @@ package dsp.schema.repo import zio._ import dsp.schema.domain.SchemaDomain.{UserID, UserProfile} - trait SchemaRepo { def lookup(id: UserID): Task[UserProfile] def update(id: UserID, profile: UserProfile): Task[Unit] diff --git a/dsp-schema/core/src/test/scala/dsp/schema/domain/SchemaCommandsSpec.scala b/dsp-schema/core/src/test/scala/dsp/schema/domain/SchemaCommandsSpec.scala index 677f0acd32..352f3e7890 100644 --- a/dsp-schema/core/src/test/scala/dsp/schema/domain/SchemaCommandsSpec.scala +++ b/dsp-schema/core/src/test/scala/dsp/schema/domain/SchemaCommandsSpec.scala @@ -32,7 +32,7 @@ object SchemaCommandsSpec extends ZIOSpecDefault { comment = Some(commentLangString) guiAttribute <- Schema.GuiAttribute.make("hlist=") guiElement <- Schema.GuiElement.make(SalsahGui.List) - guiObject <- Schema.GuiObject.make(guiAttributes = List(guiAttribute), guiElement = Some(guiElement)) + guiObject <- Schema.GuiObject.make(guiAttributes = Set(guiAttribute), guiElement = Some(guiElement)) command = CreatePropertyCommand.make( ontologyIri = ontologyIri, lastModificationDate = lastModificationDate, diff --git a/test_data/ontologies/freetest-onto.ttl b/test_data/ontologies/freetest-onto.ttl index a9ba3514c3..f7bfcfbc47 100644 --- a/test_data/ontologies/freetest-onto.ttl +++ b/test_data/ontologies/freetest-onto.ttl @@ -99,6 +99,57 @@ salsah-gui:guiElement salsah-gui:List ; salsah-gui:guiAttribute "hlist=" . +:hasPublicationDate + rdf:type owl:ObjectProperty ; + rdfs:subPropertyOf knora-base:hasValue ; + rdfs:label "Publikationsdatum"@de, + "Publication date"@en ; + knora-base:objectClassConstraint knora-base:TextValue ; + salsah-gui:guiElement salsah-gui:SimpleText ; + salsah-gui:guiAttribute "size=80", + "maxlength=255" . + +:PubMayHaveMany + rdf:type owl:Class ; + rdfs:subClassOf knora-base:Resource, + [ rdf:type owl:Restriction ; + owl:onProperty :hasPublicationDate ; + owl:minCardinality "0"^^xsd:nonNegativeInteger ; + salsah-gui:guiOrder "1"^^xsd:nonNegativeInteger ]; + rdfs:label "0-n"@en; + rdfs:comment """A comment"""@de . + +:PubMayHaveOne + rdf:type owl:Class ; + rdfs:subClassOf knora-base:Resource, + [ rdf:type owl:Restriction ; + owl:onProperty :hasPublicationDate ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ; + salsah-gui:guiOrder "1"^^xsd:nonNegativeInteger ]; + rdfs:label "0-1"@en; + rdfs:comment """A comment"""@de . + +:PubMustHaveSome + rdf:type owl:Class ; + rdfs:subClassOf knora-base:Resource, + [ rdf:type owl:Restriction ; + owl:onProperty :hasPublicationDate ; + owl:minCardinality "1"^^xsd:nonNegativeInteger ; + salsah-gui:guiOrder "1"^^xsd:nonNegativeInteger ]; + rdfs:label "1-n"@en; + rdfs:comment """A comment"""@de . + +:PubMustHaveOne + rdf:type owl:Class ; + rdfs:subClassOf knora-base:Resource, + [ rdf:type owl:Restriction ; + owl:onProperty :hasPublicationDate ; + owl:cardinality "1"^^xsd:nonNegativeInteger ; + salsah-gui:guiOrder "1"^^xsd:nonNegativeInteger ]; + rdfs:label "1"@en; + rdfs:comment """A comment"""@de . + + :FreeTest diff --git a/webapi/src/main/scala/org/knora/webapi/messages/util/MessageUtil.scala b/webapi/src/main/scala/org/knora/webapi/messages/util/MessageUtil.scala index cc81bfc777..66db69239f 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/util/MessageUtil.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/util/MessageUtil.scala @@ -5,10 +5,12 @@ package org.knora.webapi.messages.util +import dsp.schema.domain.Cardinality +import dsp.schema.domain.Cardinality._ import org.apache.commons.text.StringEscapeUtils import org.knora.webapi.OntologySchema import org.knora.webapi.messages.SmartIri -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality import java.time.Instant import scala.reflect.runtime.{universe => ru} @@ -58,23 +60,22 @@ object MessageUtil { case instant: Instant => "Instant.parse(\"" + instant.toString + "\")" case None => "None" - // Handle enumerations. - - case cardinality: Cardinality.Value => + // Handle value objects. + case cardinality: Cardinality => cardinality match { - case Cardinality.MayHaveOne => "Cardinality.MayHaveOne" - case Cardinality.MayHaveMany => "Cardinality.MayHaveMany" - case Cardinality.MustHaveOne => "Cardinality.MustHaveOne" - case Cardinality.MustHaveSome => "Cardinality.MustHaveSome" + case MayHaveOne => "MayHaveOne" + case MayHaveMany => "MayHaveMany" + case MustHaveOne => "MustHaveOne" + case MustHaveSome => "MustHaveSome" } + // Handle enumerations. case enumVal if enumVal.getClass.getName == "scala.Enumeration$Val" => enumVal.toString case ontologySchema: OntologySchema => ontologySchema.getClass.getSimpleName.stripSuffix("$") // Handle collections. - case Nil => "Nil" case list: Seq[Any @unchecked] => diff --git a/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala index 2545cf0b3b..04c03e5c80 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala @@ -6,11 +6,12 @@ package org.knora.webapi.messages.util.standoff import akka.actor.ActorRef -import com.typesafe.scalalogging.Logger import akka.pattern.ask import akka.util.Timeout -import org.knora.webapi.IRI +import com.typesafe.scalalogging.Logger import dsp.errors._ +import dsp.schema.domain.Cardinality._ +import org.knora.webapi.IRI import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.SmartIri @@ -23,7 +24,7 @@ import org.knora.webapi.messages.v1.responder.valuemessages.JulianDayNumberValue import org.knora.webapi.messages.v1.responder.valuemessages.KnoraCalendarV1 import org.knora.webapi.messages.v1.responder.valuemessages.KnoraPrecisionV1 import org.knora.webapi.messages.v1.responder.valuemessages.UpdateValueV1 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.messages.v2.responder.standoffmessages._ import org.knora.webapi.settings.KnoraSettingsImpl @@ -208,7 +209,7 @@ object StandoffTagUtilV2 { // filter all the required props val mustExistOnce: Set[SmartIri] = classSpecificProps.filter { case (propIri, card) => - card.cardinality == Cardinality.MustHaveOne || card.cardinality == Cardinality.MustHaveSome + card.cardinality == MustHaveOne || card.cardinality == MustHaveSome }.keySet // check if all the min cardinalities are respected @@ -225,7 +226,7 @@ object StandoffTagUtilV2 { // filter all the props that have a limited occurrence val mayExistOnce = classSpecificProps.filter { case (propIri, card) => - card.cardinality == Cardinality.MustHaveOne || card.cardinality == Cardinality.MayHaveOne + card.cardinality == MustHaveOne || card.cardinality == MayHaveOne }.keySet // check if all the max cardinalities are respected diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v1/responder/ontologymessages/OntologyMessagesV1.scala b/webapi/src/main/scala/org/knora/webapi/messages/v1/responder/ontologymessages/OntologyMessagesV1.scala index 313d86306c..919f031f17 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v1/responder/ontologymessages/OntologyMessagesV1.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v1/responder/ontologymessages/OntologyMessagesV1.scala @@ -6,16 +6,17 @@ package org.knora.webapi.messages.v1.responder.ontologymessages import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport +import dsp.schema.domain.Cardinality import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ +import org.knora.webapi.messages.ResponderRequest.KnoraRequestV1 import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import org.knora.webapi.messages.ResponderRequest.KnoraRequestV1 import org.knora.webapi.messages.v1.responder.KnoraResponseV1 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages.EntityInfoContentV2 +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages.ReadClassInfoV2 import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.messages.v2.responder.standoffmessages.StandoffDataTypeClasses @@ -614,7 +615,6 @@ case class PropertyTypeV1(id: IRI, label: String) { * A spray-json protocol for generating Knora API v1 JSON providing data about resources and their properties. */ object ResourceTypeV1JsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with NullOptions { - implicit val propertyDefinitionV1Format: JsonFormat[PropertyDefinitionV1] = jsonFormat10(PropertyDefinitionV1) implicit val propertyDefinitionInNamedGraphV1Format: JsonFormat[PropertyDefinitionInNamedGraphV1] = jsonFormat8( PropertyDefinitionInNamedGraphV1 diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala index cc5d0b26bb..f1be74dfb0 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala @@ -5,6 +5,7 @@ package org.knora.webapi.messages.v2.responder.ontologymessages +import dsp.schema.domain.Cardinality._ import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants @@ -13,7 +14,7 @@ import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.store.triplestoremessages.OntologyLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.SmartIriLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ /** * Rules for converting `knora-base` (or an ontology based on it) into `knora-api` in the [[ApiV2Complex]] schema. @@ -1438,110 +1439,110 @@ object KnoraBaseToApiV2ComplexTransformationRules extends OntologyTransformation ) private val ResourceCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.HasIncomingLinkValue -> Cardinality.MayHaveMany, - OntologyConstants.KnoraApiV2Complex.ArkUrl -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.VersionArkUrl -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.VersionDate -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.UserHasPermission -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.IsDeleted -> Cardinality.MayHaveOne + OntologyConstants.KnoraApiV2Complex.HasIncomingLinkValue -> MayHaveMany, + OntologyConstants.KnoraApiV2Complex.ArkUrl -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.VersionArkUrl -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.VersionDate -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.UserHasPermission -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.IsDeleted -> MayHaveOne ) private val DateBaseCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.DateValueHasStartYear -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasEndYear -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasStartMonth -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasEndMonth -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasStartDay -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasEndDay -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasStartEra -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasEndEra -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.DateValueHasCalendar -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.DateValueHasStartYear -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasEndYear -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasStartMonth -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasEndMonth -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasStartDay -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasEndDay -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasStartEra -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasEndEra -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.DateValueHasCalendar -> MustHaveOne ) private val UriBaseCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.UriValueAsUri -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.UriValueAsUri -> MustHaveOne ) private val BooleanBaseCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.BooleanValueAsBoolean -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.BooleanValueAsBoolean -> MustHaveOne ) private val IntBaseCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.IntValueAsInt -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.IntValueAsInt -> MustHaveOne ) private val DecimalBaseCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.DecimalValueAsDecimal -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.DecimalValueAsDecimal -> MustHaveOne ) private val IntervalBaseCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.IntervalValueHasStart -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.IntervalValueHasEnd -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.IntervalValueHasStart -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.IntervalValueHasEnd -> MustHaveOne ) private val ColorBaseCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.ColorValueAsColor -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.ColorValueAsColor -> MustHaveOne ) private val ValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.ValueAsString -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.HasPermissions -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.UserHasPermission -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.ArkUrl -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.VersionArkUrl -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.IsDeleted -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.ValueHasUUID -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.ValueAsString -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.HasPermissions -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.UserHasPermission -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.ArkUrl -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.VersionArkUrl -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.IsDeleted -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.ValueHasUUID -> MustHaveOne ) private val TextValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.TextValueHasStandoff -> Cardinality.MayHaveMany, - OntologyConstants.KnoraApiV2Complex.TextValueHasMarkup -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.TextValueHasLanguage -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.TextValueAsXml -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.TextValueAsHtml -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.TextValueHasMapping -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.TextValueHasMaxStandoffStartIndex -> Cardinality.MayHaveOne + OntologyConstants.KnoraApiV2Complex.TextValueHasStandoff -> MayHaveMany, + OntologyConstants.KnoraApiV2Complex.TextValueHasMarkup -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.TextValueHasLanguage -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.TextValueAsXml -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.TextValueAsHtml -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.TextValueHasMapping -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.TextValueHasMaxStandoffStartIndex -> MayHaveOne ) private val StandoffTagCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.StandoffTagHasStartParentIndex -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.StandoffTagHasEndParentIndex -> Cardinality.MayHaveOne + OntologyConstants.KnoraApiV2Complex.StandoffTagHasStartParentIndex -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.StandoffTagHasEndParentIndex -> MayHaveOne ) private val LinkValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.LinkValueHasSource -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.LinkValueHasTarget -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.LinkValueHasSourceIri -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.LinkValueHasTargetIri -> Cardinality.MayHaveOne + OntologyConstants.KnoraApiV2Complex.LinkValueHasSource -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.LinkValueHasTarget -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.LinkValueHasSourceIri -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.LinkValueHasTargetIri -> MayHaveOne ) private val GeomValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.GeometryValueAsGeometry -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.GeometryValueAsGeometry -> MustHaveOne ) private val ListValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.ListValueAsListNode -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.ListValueAsListNode -> MustHaveOne ) private val GeonameValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.GeonameValueAsGeonameCode -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.GeonameValueAsGeonameCode -> MustHaveOne ) private val FileValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.FileValueAsUrl -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.FileValueHasFilename -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.FileValueAsUrl -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.FileValueHasFilename -> MustHaveOne ) private val StillImageFileValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.StillImageFileValueHasDimX -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.StillImageFileValueHasDimY -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.StillImageFileValueHasIIIFBaseUrl -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Complex.StillImageFileValueHasDimX -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.StillImageFileValueHasDimY -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.StillImageFileValueHasIIIFBaseUrl -> MustHaveOne ) private val DocumentFileValueCardinalities = Map( - OntologyConstants.KnoraApiV2Complex.DocumentFileValueHasPageCount -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Complex.DocumentFileValueHasDimX -> Cardinality.MayHaveOne, - OntologyConstants.KnoraApiV2Complex.DocumentFileValueHasDimY -> Cardinality.MayHaveOne + OntologyConstants.KnoraApiV2Complex.DocumentFileValueHasPageCount -> MustHaveOne, + OntologyConstants.KnoraApiV2Complex.DocumentFileValueHasDimX -> MayHaveOne, + OntologyConstants.KnoraApiV2Complex.DocumentFileValueHasDimY -> MayHaveOne ) /** @@ -1652,7 +1653,7 @@ object KnoraBaseToApiV2ComplexTransformationRules extends OntologyTransformation OntologyConstants.KnoraApiV2Complex.DocumentFileValue -> DocumentFileValueCardinalities ).map { case (classIri, cardinalities) => classIri.toSmartIri -> cardinalities.map { case (propertyIri, cardinality) => - propertyIri.toSmartIri -> Cardinality.KnoraCardinalityInfo(cardinality) + propertyIri.toSmartIri -> KnoraCardinalityInfo(cardinality) } } diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2SimpleTransformationRules.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2SimpleTransformationRules.scala index 30858041e0..df82614486 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2SimpleTransformationRules.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2SimpleTransformationRules.scala @@ -5,6 +5,7 @@ package org.knora.webapi.messages.v2.responder.ontologymessages +import dsp.schema.domain.Cardinality._ import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants @@ -13,7 +14,7 @@ import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.store.triplestoremessages.OntologyLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.SmartIriLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ /** * Rules for converting `knora-base` (or an ontology based on it) into `knora-api` in the [[ApiV2Simple]] schema. @@ -397,9 +398,9 @@ object KnoraBaseToApiV2SimpleTransformationRules extends OntologyTransformationR ) private val ResourceCardinalites = Map( - OntologyConstants.KnoraApiV2Simple.HasIncomingLink -> Cardinality.MayHaveMany, - OntologyConstants.KnoraApiV2Simple.ArkUrl -> Cardinality.MustHaveOne, - OntologyConstants.KnoraApiV2Simple.VersionArkUrl -> Cardinality.MustHaveOne + OntologyConstants.KnoraApiV2Simple.HasIncomingLink -> MayHaveMany, + OntologyConstants.KnoraApiV2Simple.ArkUrl -> MustHaveOne, + OntologyConstants.KnoraApiV2Simple.VersionArkUrl -> MustHaveOne ) /** @@ -543,7 +544,7 @@ object KnoraBaseToApiV2SimpleTransformationRules extends OntologyTransformationR OntologyConstants.KnoraBase.Resource -> ResourceCardinalites ).map { case (classIri, cardinalities) => classIri.toSmartIri.toOntologySchema(ApiV2Simple) -> cardinalities.map { case (propertyIri, cardinality) => - propertyIri.toSmartIri.toOntologySchema(ApiV2Simple) -> Cardinality.KnoraCardinalityInfo(cardinality) + propertyIri.toSmartIri.toOntologySchema(ApiV2Simple) -> KnoraCardinalityInfo(cardinality) } } diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala index 64b70c9ef3..538d9d54a2 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala @@ -13,6 +13,8 @@ import dsp.errors.AssertionException import dsp.errors.BadRequestException import dsp.errors.DataConversionException import dsp.errors.InconsistentRepositoryDataException +import dsp.schema.domain.Cardinality +import dsp.schema.domain.Cardinality._ import dsp.valueobjects.Iri import dsp.valueobjects.Schema import org.apache.commons.lang3.builder.HashCodeBuilder @@ -26,8 +28,8 @@ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.messages.util.rdf._ import org.knora.webapi.messages.v2.responder._ -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.OwlCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.OwlCardinalityInfo import org.knora.webapi.messages.v2.responder.standoffmessages.StandoffDataTypeClasses import org.knora.webapi.settings.KnoraSettingsImpl @@ -2126,7 +2128,7 @@ case class PredicateInfoV2(predicateIri: SmartIri, objects: Seq[OntologyLiteralV /** * Represents the OWL cardinalities that Knora supports. */ -object Cardinality extends Enumeration { +object OwlCardinality extends Enumeration { /** * Represents information about an OWL cardinality. @@ -2158,30 +2160,25 @@ object Cardinality extends Enumeration { * @param cardinality the Knora cardinality. * @param guiOrder the SALSAH GUI order. */ - case class KnoraCardinalityInfo(cardinality: Value, guiOrder: Option[Int] = None) { + case class KnoraCardinalityInfo(cardinality: Cardinality, guiOrder: Option[Int] = None) { self => override def toString: String = guiOrder match { - case Some(definedGuiOrder) => s"$cardinality (guiOrder $definedGuiOrder)" - case None => cardinality.toString + case Some(definedGuiOrder) => s"${cardinality.value} (guiOrder $definedGuiOrder)" + case None => cardinality.value } def equalsWithoutGuiOrder(that: KnoraCardinalityInfo): Boolean = that.cardinality == cardinality - } - - type Cardinality = Value - - val MayHaveOne: Value = Value(0, "0-1") - val MayHaveMany: Value = Value(1, "0-n") - val MustHaveOne: Value = Value(2, "1") - val MustHaveSome: Value = Value(3, "1-n") - val valueMap: Map[String, Value] = values.map(v => (v.toString, v)).toMap + } /** * The valid mappings between Knora cardinalities and OWL cardinalities. */ - private val knoraCardinality2OwlCardinalityMap: Map[Value, OwlCardinalityInfo] = Map( - MayHaveOne -> OwlCardinalityInfo(owlCardinalityIri = OntologyConstants.Owl.MaxCardinality, owlCardinalityValue = 1), + private val knoraCardinality2OwlCardinalityMap: Map[Cardinality, OwlCardinalityInfo] = Map( + MayHaveOne -> OwlCardinalityInfo( + owlCardinalityIri = OntologyConstants.Owl.MaxCardinality, + owlCardinalityValue = 1 + ), MayHaveMany -> OwlCardinalityInfo( owlCardinalityIri = OntologyConstants.Owl.MinCardinality, owlCardinalityValue = 0 @@ -2193,24 +2190,11 @@ object Cardinality extends Enumeration { ) ) - private val owlCardinality2KnoraCardinalityMap: Map[OwlCardinalityInfo, Value] = + private val owlCardinality2KnoraCardinalityMap: Map[OwlCardinalityInfo, Cardinality] = knoraCardinality2OwlCardinalityMap.map { case (knoraC, owlC) => (owlC, knoraC) } - /** - * Given the name of a value in this enumeration, returns the value. If the value is not found, throws an - * [[InconsistentRepositoryDataException]]. - * - * @param name the name of the value. - * @return the requested value. - */ - def lookup(name: String): Value = - valueMap.get(name) match { - case Some(value) => value - case None => throw InconsistentRepositoryDataException(s"Cardinality not found: $name") - } - /** * Converts information about an OWL cardinality restriction to a [[Value]] of this enumeration. * @@ -2239,26 +2223,6 @@ object Cardinality extends Enumeration { def knoraCardinality2OwlCardinality(knoraCardinality: KnoraCardinalityInfo): OwlCardinalityInfo = knoraCardinality2OwlCardinalityMap(knoraCardinality.cardinality).copy(guiOrder = knoraCardinality.guiOrder) - /** - * Checks whether a cardinality that is directly defined on a class is compatible with an inherited cardinality on the - * same property. This will be true only if the directly defined cardinality is at least as restrictive as the - * inherited one. - * - * @param directCardinality the directly defined cardinality. - * @param inheritableCardinality the inherited cardinality. - * @return `true` if the directly defined cardinality is compatible with the inherited one. - */ - def isCompatible(directCardinality: Value, inheritableCardinality: Value): Boolean = - if (directCardinality == inheritableCardinality) { - true - } else { - inheritableCardinality match { - case MayHaveOne => directCardinality == MustHaveOne - case MayHaveMany => true - case MustHaveOne => false - case MustHaveSome => directCardinality == MustHaveOne - } - } } /** @@ -2667,7 +2631,7 @@ sealed trait ReadEntityInfoV2 { * @param isStandoffClass `true` if this is a subclass of `knora-base:StandoffTag`. * @param isValueClass `true` if the class is a Knora value class. * @param canBeInstantiated `true` if the class is a Knora resource class that can be instantiated via the API. - * @param inheritedCardinalities a [[Map]] of properties to [[Cardinality.Value]] objects representing the class's + * @param inheritedCardinalities a [[Map]] of properties to [[Cardinality]] objects representing the class's * inherited cardinalities on those properties. * @param standoffDataType if this is a standoff tag class, the standoff datatype tag class (if any) that it * is a subclass of. @@ -2774,7 +2738,7 @@ case class ReadClassInfoV2( // Add cardinalities that this class inherits in the target schema but not in the source schema. - val baseClassesInTargetSchema = allBaseClasses.map(_.toOntologySchema(targetSchema)) + val baseClassesInTargetSchema: Seq[SmartIri] = allBaseClasses.map(_.toOntologySchema(targetSchema)) val inheritedCardinalitiesToAdd: Map[SmartIri, KnoraCardinalityInfo] = baseClassesInTargetSchema.flatMap { baseClassIri => @@ -2812,10 +2776,10 @@ case class ReadClassInfoV2( cardinalityInfo.guiOrder }.toIndexedSeq.map { case (propertyIri: SmartIri, cardinalityInfo: KnoraCardinalityInfo) => val prop2card: (IRI, JsonLDInt) = cardinalityInfo.cardinality match { - case Cardinality.MayHaveMany => OntologyConstants.Owl.MinCardinality -> JsonLDInt(0) - case Cardinality.MayHaveOne => OntologyConstants.Owl.MaxCardinality -> JsonLDInt(1) - case Cardinality.MustHaveOne => OntologyConstants.Owl.Cardinality -> JsonLDInt(1) - case Cardinality.MustHaveSome => OntologyConstants.Owl.MinCardinality -> JsonLDInt(1) + case MayHaveMany => OntologyConstants.Owl.MinCardinality -> JsonLDInt(0) + case MayHaveOne => OntologyConstants.Owl.MaxCardinality -> JsonLDInt(1) + case MustHaveOne => OntologyConstants.Owl.Cardinality -> JsonLDInt(1) + case MustHaveSome => OntologyConstants.Owl.MinCardinality -> JsonLDInt(1) } // If we're using the complex schema and the cardinality is inherited, add an annotation to say so. @@ -3103,7 +3067,7 @@ case class DatatypeInfoV2(onDatatype: SmartIri, pattern: Option[String] = None) * * @param classIri the IRI of the class. * @param predicates a [[Map]] of predicate IRIs to [[PredicateInfoV2]] objects. - * @param directCardinalities a [[Map]] of properties to [[Cardinality.Value]] objects representing the cardinalities + * @param directCardinalities a [[Map]] of properties to [[Cardinality]] objects representing the cardinalities * that are directly defined on the class (as opposed to inherited) on those properties. * @param datatypeInfo if the class's `rdf:type` is `rdfs:Datatype`, a [[DatatypeInfoV2]] describing it. * @param subClassOf the classes that this class is a subclass of. @@ -3357,7 +3321,7 @@ object ClassInfoContentV2 { guiOrder = guiOrder ) - val knoraCardinalityInfo = Cardinality.owlCardinality2KnoraCardinality( + val knoraCardinalityInfo = OwlCardinality.owlCardinality2KnoraCardinality( propertyIri = onProperty.toString, owlCardinality = owlCardinalityInfo ) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyTransformationRules.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyTransformationRules.scala index 1e9a4b1257..791ee2eecb 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyTransformationRules.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyTransformationRules.scala @@ -9,7 +9,7 @@ import org.knora.webapi.ApiV2Complex import org.knora.webapi.ApiV2Schema import org.knora.webapi.ApiV2Simple import org.knora.webapi.messages.SmartIri -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo /** * A trait for objects that provide rules for converting an ontology from the internal schema to an external schema. diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v1/OntologyResponderV1.scala b/webapi/src/main/scala/org/knora/webapi/responders/v1/OntologyResponderV1.scala index 1ea24372d7..1d29a9beab 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v1/OntologyResponderV1.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v1/OntologyResponderV1.scala @@ -6,10 +6,10 @@ package org.knora.webapi.responders.v1 import akka.pattern._ -import org.knora.webapi._ +import dsp.constants.SalsahGui import dsp.errors.InconsistentRepositoryDataException import dsp.errors.NotFoundException - +import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM @@ -21,13 +21,12 @@ import org.knora.webapi.messages.util.ValueUtilV1 import org.knora.webapi.messages.v1.responder.ontologymessages._ import org.knora.webapi.messages.v1.responder.resourcemessages.SalsahGuiConversions import org.knora.webapi.messages.v2.responder.SuccessResponseV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.responders.Responder import org.knora.webapi.responders.Responder.handleUnexpectedMessage import scala.concurrent.Future -import dsp.constants.SalsahGui /** * Handles requests for information about ontology entities. @@ -251,7 +250,7 @@ class OntologyResponderV1(responderData: ResponderData) extends Responder(respon ) ), vocabulary = entityInfo.ontologyIri, - occurrence = cardinalityInfo.cardinality.toString, + occurrence = cardinalityInfo.cardinality.value, valuetype_id = OntologyConstants.KnoraBase.LinkValue, attributes = valueUtilV1.makeAttributeString( @@ -301,7 +300,7 @@ class OntologyResponderV1(responderData: ResponderData) extends Responder(respon ) ), vocabulary = entityInfo.ontologyIri, - occurrence = cardinalityInfo.cardinality.toString, + occurrence = cardinalityInfo.cardinality.value, valuetype_id = entityInfo .getPredicateObject( OntologyConstants.KnoraBase.ObjectClassConstraint diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala b/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala index 9eb8192a0b..6c3643eb83 100755 --- a/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala @@ -7,9 +7,10 @@ package org.knora.webapi.responders.v1 import akka.http.scaladsl.util.FastFuture import akka.pattern._ -import org.knora.webapi._ +import dsp.constants.SalsahGui import dsp.errors._ - +import dsp.schema.domain.Cardinality._ +import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.SmartIri @@ -34,10 +35,10 @@ import org.knora.webapi.messages.v1.responder.projectmessages._ import org.knora.webapi.messages.v1.responder.resourcemessages._ import org.knora.webapi.messages.v1.responder.valuemessages._ import org.knora.webapi.messages.v2.responder.UpdateResultInProject -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages.OntologyMetadataGetByIriRequestV2 import org.knora.webapi.messages.v2.responder.ontologymessages.OntologyMetadataV2 +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages.ReadOntologyMetadataV2 import org.knora.webapi.messages.v2.responder.valuemessages.FileValueContentV2 import org.knora.webapi.responders.IriLocker @@ -53,7 +54,6 @@ import scala.concurrent.Future import scala.util.Failure import scala.util.Success import scala.util.Try -import dsp.constants.SalsahGui /** * Responds to requests for information about resources, and returns responses in Knora API v1 format. @@ -874,7 +874,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo predicateIri = OntologyConstants.Rdfs.Label, preferredLangs = Some(userProfile.lang, settings.fallbackLanguage) ), - occurrence = Some(propsAndCardinalities(propertyIri).cardinality.toString), + occurrence = Some(propsAndCardinalities(propertyIri).cardinality.value), attributes = (propertyEntityInfo.getPredicateStringObjectsWithoutLang( SalsahGui.GuiAttribute ) + valueUtilV1.makeAttributeRestype( @@ -905,7 +905,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo predicateIri = OntologyConstants.Rdfs.Label, preferredLangs = Some(userProfile.lang, settings.fallbackLanguage) ), - occurrence = Some(propsAndCardinalities(propertyIri).cardinality.toString), + occurrence = Some(propsAndCardinalities(propertyIri).cardinality.value), attributes = propertyEntityInfo .getPredicateStringObjectsWithoutLang( SalsahGui.GuiAttribute @@ -2052,7 +2052,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo ) if ( - (cardinalityInfo.cardinality == Cardinality.MayHaveOne || cardinalityInfo.cardinality == Cardinality.MustHaveOne) && valuesForProperty.size > 1 + (cardinalityInfo.cardinality == MayHaveOne || cardinalityInfo.cardinality == MustHaveOne) && valuesForProperty.size > 1 ) { throw OntologyConstraintException( s"Resource class $resourceClassIri does not allow more than one value for property $propertyIri" @@ -2062,7 +2062,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo // Check that no required values are missing. requiredProps: Set[IRI] = resourceClassInfo.knoraResourceCardinalities.filter { case (_, cardinalityInfo) => - cardinalityInfo.cardinality == Cardinality.MustHaveOne || cardinalityInfo.cardinality == Cardinality.MustHaveSome + cardinalityInfo.cardinality == MustHaveOne || cardinalityInfo.cardinality == MustHaveSome }.keySet -- resourceClassInfo.linkValueProperties -- resourceClassInfo.fileValueProperties // exclude link value and file value properties from checking submittedPropertyIris = values.keySet @@ -3230,7 +3230,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo preferredLangs = Some(userProfile.lang, settings.fallbackLanguage) ) ), - occurrence = propertyCardinality.map(_.cardinality.toString), + occurrence = propertyCardinality.map(_.cardinality.value), attributes = propertyEntityInfo match { case Some(entityInfo) => if (entityInfo.isLinkProp) { @@ -3343,7 +3343,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo // is MustHaveOne or MayHaveOne, don't return any information about the property. propsAndCardinalities.get(propertyIri) match { case Some(cardinalityInfo) - if (cardinalityInfo.cardinality == Cardinality.MustHaveOne || cardinalityInfo.cardinality == Cardinality.MayHaveOne) && valueObjectsV1Sorted.nonEmpty && valueObjectListFiltered.isEmpty => + if (cardinalityInfo.cardinality == MustHaveOne || cardinalityInfo.cardinality == MayHaveOne) && valueObjectsV1Sorted.nonEmpty && valueObjectListFiltered.isEmpty => None case _ => Some(propertyV1) } @@ -3512,7 +3512,7 @@ class ResourcesResponderV1(responderData: ResponderData) extends Responder(respo // is MustHaveOne or MayHaveOne, don't return any information about the property. } yield propsAndCardinalities.get(propertyIri) match { case Some(cardinalityInfo) - if (cardinalityInfo.cardinality == Cardinality.MustHaveOne || cardinalityInfo.cardinality == Cardinality.MayHaveOne) && valueObjectsV1.nonEmpty && valueObjectListFiltered.isEmpty => + if (cardinalityInfo.cardinality == MustHaveOne || cardinalityInfo.cardinality == MayHaveOne) && valueObjectsV1.nonEmpty && valueObjectListFiltered.isEmpty => None case _ => Some(propertyV1) } diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v1/ValuesResponderV1.scala b/webapi/src/main/scala/org/knora/webapi/responders/v1/ValuesResponderV1.scala index ef579dc951..fcb0bee4df 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v1/ValuesResponderV1.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v1/ValuesResponderV1.scala @@ -6,9 +6,9 @@ package org.knora.webapi.responders.v1 import akka.pattern._ -import org.knora.webapi._ import dsp.errors._ - +import dsp.schema.domain.Cardinality._ +import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.StringFormatter @@ -38,7 +38,7 @@ import org.knora.webapi.messages.v1.responder.usermessages.UserProfileByIRIGetV1 import org.knora.webapi.messages.v1.responder.usermessages.UserProfileTypeV1 import org.knora.webapi.messages.v1.responder.usermessages.UserProfileV1 import org.knora.webapi.messages.v1.responder.valuemessages._ -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality import org.knora.webapi.messages.v2.responder.standoffmessages._ import org.knora.webapi.messages.v2.responder.valuemessages.FileValueContentV2 import org.knora.webapi.responders.IriLocker @@ -224,8 +224,7 @@ class ValuesResponderV1(responderData: ResponderData) extends Responder(responde throw DuplicateValueException() } - val propCardinality = Cardinality.lookup(prop.occurrence.get) - !((propCardinality == Cardinality.MayHaveOne || propCardinality == Cardinality.MustHaveOne) && prop.values.nonEmpty) + !((prop.occurrence.get == MayHaveOne.value || prop.occurrence.get == MustHaveOne.value) && prop.values.nonEmpty) case None => false diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala index b38c42e502..a92f39deef 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala @@ -9,6 +9,7 @@ import akka.http.scaladsl.util.FastFuture import akka.pattern._ import dsp.constants.SalsahGui import dsp.errors._ +import dsp.schema.domain.Cardinality._ import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants @@ -27,14 +28,14 @@ import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.util.ResponderData import org.knora.webapi.messages.v2.responder.CanDoResponseV2 import org.knora.webapi.messages.v2.responder.SuccessResponseV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.responders.IriLocker import org.knora.webapi.responders.Responder import org.knora.webapi.responders.Responder.handleUnexpectedMessage import org.knora.webapi.responders.v2.ontology.Cache import org.knora.webapi.responders.v2.ontology.Cache.ONTOLOGY_CACHE_LOCK_IRI -import org.knora.webapi.responders.v2.ontology.Cardinalities +import org.knora.webapi.responders.v2.ontology.CardinalityHandler import org.knora.webapi.responders.v2.ontology.OntologyHelpers import org.knora.webapi.util._ @@ -1321,7 +1322,7 @@ class OntologyResponderV2(responderData: ResponderData) extends Responder(respon hasCardinality: Option[(SmartIri, KnoraCardinalityInfo)] = addCardinalitiesRequest.classInfoContent.directCardinalities.find { case (_, constraint: KnoraCardinalityInfo) => - constraint.cardinality == Cardinality.MustHaveSome || constraint.cardinality == Cardinality.MustHaveOne + constraint.cardinality == MustHaveSome || constraint.cardinality == MustHaveOne } _ <- hasCardinality match { @@ -1774,7 +1775,7 @@ class OntologyResponderV2(responderData: ResponderData) extends Responder(respon apiRequestID = canDeleteCardinalitiesFromClassRequest.apiRequestID, iri = ONTOLOGY_CACHE_LOCK_IRI, task = () => - Cardinalities.canDeleteCardinalitiesFromClass( + CardinalityHandler.canDeleteCardinalitiesFromClass( settings, appActor, deleteCardinalitiesFromClassRequest = canDeleteCardinalitiesFromClassRequest, @@ -1814,7 +1815,7 @@ class OntologyResponderV2(responderData: ResponderData) extends Responder(respon apiRequestID = deleteCardinalitiesFromClassRequest.apiRequestID, iri = ONTOLOGY_CACHE_LOCK_IRI, task = () => - Cardinalities.deleteCardinalitiesFromClass( + CardinalityHandler.deleteCardinalitiesFromClass( settings, appActor, deleteCardinalitiesFromClassRequest = deleteCardinalitiesFromClassRequest, diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala index 76e399fc6f..83c061cac8 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala @@ -9,6 +9,7 @@ import akka.http.scaladsl.util.FastFuture import akka.pattern._ import akka.stream.Materializer import dsp.errors._ +import dsp.schema.domain.Cardinality._ import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants @@ -23,12 +24,12 @@ import org.knora.webapi.messages.store.sipimessages.SipiGetTextFileResponse import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.messages.twirl.SparqlTemplateResourceToCreate import org.knora.webapi.messages.util.ConstructResponseUtilV2.MappingAndXSLTransformation +import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.util.PermissionUtilADM.AGreaterThanB import org.knora.webapi.messages.util.PermissionUtilADM.DeletePermission import org.knora.webapi.messages.util.PermissionUtilADM.ModifyPermission import org.knora.webapi.messages.util.PermissionUtilADM.PermissionComparisonResult import org.knora.webapi.messages.util._ -import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.util.rdf.JsonLDArray import org.knora.webapi.messages.util.rdf.JsonLDDocument import org.knora.webapi.messages.util.rdf.JsonLDInt @@ -42,6 +43,7 @@ import org.knora.webapi.messages.util.search.gravsearch.GravsearchParser import org.knora.webapi.messages.util.standoff.StandoffTagUtilV2 import org.knora.webapi.messages.v2.responder.SuccessResponseV2 import org.knora.webapi.messages.v2.responder.UpdateResultInProject +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.messages.v2.responder.resourcemessages._ import org.knora.webapi.messages.v2.responder.searchmessages.GravsearchRequestV2 @@ -793,7 +795,7 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt // Check that the resource class has a suitable cardinality for each submitted value. resourceClassInfo <- Future(entityInfo.classInfoMap(internalCreateResource.resourceClassIri)) - knoraPropertyCardinalities: Map[SmartIri, Cardinality.KnoraCardinalityInfo] = + knoraPropertyCardinalities: Map[SmartIri, KnoraCardinalityInfo] = resourceClassInfo.allCardinalities.view .filterKeys(resourceClassInfo.knoraResourceProperties) .toMap @@ -811,7 +813,7 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt ) if ( - (cardinalityInfo.cardinality == Cardinality.MayHaveOne || cardinalityInfo.cardinality == Cardinality.MustHaveOne) && valuesForProperty.size > 1 + (cardinalityInfo.cardinality == MayHaveOne || cardinalityInfo.cardinality == MustHaveOne) && valuesForProperty.size > 1 ) { throw OntologyConstraintException( s"${resourceIDForErrorMsg}Resource class <${internalCreateResource.resourceClassIri @@ -823,7 +825,7 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt // Check that no required values are missing. requiredProps: Set[SmartIri] = knoraPropertyCardinalities.filter { case (_, cardinalityInfo) => - cardinalityInfo.cardinality == Cardinality.MustHaveOne || cardinalityInfo.cardinality == Cardinality.MustHaveSome + cardinalityInfo.cardinality == MustHaveOne || cardinalityInfo.cardinality == MustHaveSome }.keySet -- resourceClassInfo.linkProperties internalPropertyIris: Set[SmartIri] = internalCreateResource.values.keySet diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/StandoffResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/StandoffResponderV2.scala index 7320dd2089..f8df0ea45e 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/StandoffResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/StandoffResponderV2.scala @@ -8,9 +8,9 @@ package org.knora.webapi.responders.v2 import akka.pattern._ import akka.stream.Materializer import akka.util.Timeout -import org.knora.webapi._ import dsp.errors._ - +import dsp.schema.domain.Cardinality._ +import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.SmartIri @@ -30,8 +30,7 @@ import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.util.ResponderData import org.knora.webapi.messages.util.standoff.StandoffTagUtilV2 import org.knora.webapi.messages.util.standoff.StandoffTagUtilV2.XMLTagItem -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages.ReadClassInfoV2 import org.knora.webapi.messages.v2.responder.ontologymessages.StandoffEntityInfoGetRequestV2 import org.knora.webapi.messages.v2.responder.ontologymessages.StandoffEntityInfoGetResponseV2 @@ -1159,7 +1158,7 @@ class StandoffResponderV2(responderData: ResponderData) extends Responder(respon .standoffClassInfoMap(standoffClass.toSmartIri) .allCardinalities .filter { case (property: SmartIri, card: KnoraCardinalityInfo) => - card.cardinality == Cardinality.MustHaveOne || card.cardinality == Cardinality.MustHaveSome + card.cardinality == MustHaveOne || card.cardinality == MustHaveSome } .keySet -- StandoffProperties.systemProperties.map(_.toSmartIri) -- StandoffProperties.dataTypeProperties .map(_.toSmartIri) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala index 1e3deb1ad1..ca763c4d7f 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala @@ -8,6 +8,7 @@ package org.knora.webapi.responders.v2 import akka.http.scaladsl.util.FastFuture import akka.pattern._ import dsp.errors._ +import dsp.schema.domain.Cardinality._ import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants @@ -24,6 +25,7 @@ import org.knora.webapi.messages.util.ResponderData import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.util.search.gravsearch.GravsearchParser import org.knora.webapi.messages.v2.responder.SuccessResponseV2 +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.messages.v2.responder.resourcemessages._ import org.knora.webapi.messages.v2.responder.searchmessages.GravsearchRequestV2 @@ -172,13 +174,13 @@ class ValuesResponderV2(responderData: ResponderData) extends Responder(responde // Check that the resource class has a cardinality for the submitted property. classInfo: ReadClassInfoV2 = classInfoResponse.classes(resourceInfo.resourceClassIri) - cardinalityInfo: Cardinality.KnoraCardinalityInfo = classInfo.allCardinalities.getOrElse( - submittedInternalPropertyIri, - throw BadRequestException( - s"Resource <${createValueRequest.createValue.resourceIri}> belongs to class <${resourceInfo.resourceClassIri - .toOntologySchema(ApiV2Complex)}>, which has no cardinality for property <${createValueRequest.createValue.propertyIri}>" - ) - ) + cardinalityInfo: KnoraCardinalityInfo = classInfo.allCardinalities.getOrElse( + submittedInternalPropertyIri, + throw BadRequestException( + s"Resource <${createValueRequest.createValue.resourceIri}> belongs to class <${resourceInfo.resourceClassIri + .toOntologySchema(ApiV2Complex)}>, which has no cardinality for property <${createValueRequest.createValue.propertyIri}>" + ) + ) // Check that the object of the adjusted property (the value to be created, or the target of the link to be created) will have // the correct type for the adjusted property's knora-base:objectClassConstraint. @@ -223,7 +225,7 @@ class ValuesResponderV2(responderData: ResponderData) extends Responder(responde _ = if ( - (cardinalityInfo.cardinality == Cardinality.MustHaveOne || cardinalityInfo.cardinality == Cardinality.MustHaveSome) && currentValuesForProp.isEmpty + (cardinalityInfo.cardinality == MustHaveOne || cardinalityInfo.cardinality == MustHaveSome) && currentValuesForProp.isEmpty ) { throw InconsistentRepositoryDataException( s"Resource class <${resourceInfo.resourceClassIri @@ -233,7 +235,7 @@ class ValuesResponderV2(responderData: ResponderData) extends Responder(responde _ = if ( - cardinalityInfo.cardinality == Cardinality.MustHaveOne || (cardinalityInfo.cardinality == Cardinality.MayHaveOne && currentValuesForProp.nonEmpty) + cardinalityInfo.cardinality == MustHaveOne || (cardinalityInfo.cardinality == MayHaveOne && currentValuesForProp.nonEmpty) ) { throw OntologyConstraintException( s"Resource class <${resourceInfo.resourceClassIri @@ -1755,7 +1757,7 @@ class ValuesResponderV2(responderData: ResponderData) extends Responder(responde classInfoResponse: ReadOntologyV2 <- appActor.ask(classInfoRequest).mapTo[ReadOntologyV2] classInfo: ReadClassInfoV2 = classInfoResponse.classes(resourceInfo.resourceClassIri) - cardinalityInfo: Cardinality.KnoraCardinalityInfo = + cardinalityInfo: KnoraCardinalityInfo = classInfo.allCardinalities.getOrElse( submittedInternalPropertyIri, throw InconsistentRepositoryDataException( @@ -1772,7 +1774,7 @@ class ValuesResponderV2(responderData: ResponderData) extends Responder(responde _ = if ( - (cardinalityInfo.cardinality == Cardinality.MustHaveOne || cardinalityInfo.cardinality == Cardinality.MustHaveSome) && currentValuesForProp.size == 1 + (cardinalityInfo.cardinality == MustHaveOne || cardinalityInfo.cardinality == MustHaveSome) && currentValuesForProp.size == 1 ) { throw OntologyConstraintException( s"Resource class <${resourceInfo.resourceClassIri.toOntologySchema(ApiV2Complex)}> has a cardinality of ${cardinalityInfo.cardinality} on property <${deleteValueRequest.propertyIri}>, and this does not allow a value to be deleted for that property from resource <${deleteValueRequest.resourceIri}>" diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cache.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cache.scala index d62dd7bffb..2d54d8932c 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cache.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cache.scala @@ -33,10 +33,10 @@ import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.util.OntologyUtil import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.v2.responder.SuccessResponseV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages.ClassInfoContentV2 import org.knora.webapi.messages.v2.responder.ontologymessages.IndividualInfoContentV2 import org.knora.webapi.messages.v2.responder.ontologymessages.OntologyMetadataV2 +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages.PropertyInfoContentV2 import org.knora.webapi.messages.v2.responder.ontologymessages.ReadClassInfoV2 import org.knora.webapi.messages.v2.responder.ontologymessages.ReadOntologyV2 diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cardinalities.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/CardinalityHandler.scala similarity index 98% rename from webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cardinalities.scala rename to webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/CardinalityHandler.scala index 7a0b9c074e..a34391f636 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/Cardinalities.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/CardinalityHandler.scala @@ -22,7 +22,6 @@ import org.knora.webapi.messages.store.triplestoremessages.SparqlAskResponse import org.knora.webapi.messages.store.triplestoremessages.SparqlUpdateRequest import org.knora.webapi.messages.store.triplestoremessages.SparqlUpdateResponse import org.knora.webapi.messages.v2.responder.CanDoResponseV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.settings.KnoraSettingsImpl @@ -33,7 +32,7 @@ import scala.concurrent.Future /** * Contains methods used for dealing with cardinalities on a class */ -object Cardinalities { +object CardinalityHandler { /** * FIXME(DSP-1856): Only works if a single cardinality is supplied. @@ -103,7 +102,7 @@ object Cardinalities { // Check that the submitted cardinality to delete is defined on this class - cardinalitiesToDelete: Map[SmartIri, Cardinality.KnoraCardinalityInfo] = + cardinalitiesToDelete: Map[SmartIri, OwlCardinality.KnoraCardinalityInfo] = deleteCardinalitiesFromClassRequest.classInfoContent.toOntologySchema(InternalSchema).directCardinalities isDefinedOnClassList: List[Boolean] <- Future @@ -260,7 +259,7 @@ object Cardinalities { // Check that the submitted cardinality to delete is defined on this class - cardinalitiesToDelete: Map[SmartIri, Cardinality.KnoraCardinalityInfo] = + cardinalitiesToDelete: Map[SmartIri, OwlCardinality.KnoraCardinalityInfo] = deleteCardinalitiesFromClassRequest.classInfoContent.toOntologySchema(InternalSchema).directCardinalities isDefinedOnClassList: List[Boolean] <- Future @@ -358,7 +357,7 @@ object Cardinalities { propertyIrisOfAllCardinalitiesForClass = cardinalitiesForClassWithInheritance.keySet - inheritedCardinalities: Map[SmartIri, KnoraCardinalityInfo] = + inheritedCardinalities: Map[SmartIri, OwlCardinality.KnoraCardinalityInfo] = cardinalitiesForClassWithInheritance.filterNot { case (propertyIri, _) => newInternalClassDefWithLinkValueProps.directCardinalities.contains(propertyIri) } @@ -485,7 +484,7 @@ object Cardinalities { * @param internalOntologyIri the internal ontology IRI * @return `true` if the class is defined inside the ontology found in the cache, otherwise throws an exception. */ - def classExists( + private def classExists( cacheData: Cache.OntologyCacheData, submittedClassInfoContentV2: ClassInfoContentV2, internalClassIri: SmartIri, @@ -512,10 +511,10 @@ object Cardinalities { * @param internalOntologyIri the ontology containing the class. * @return `true` if the cardinality is defined on the class, `false` otherwise */ - def isCardinalityDefinedOnClass( + private def isCardinalityDefinedOnClass( cacheData: Cache.OntologyCacheData, propertyIri: SmartIri, - cardinalityInfo: KnoraCardinalityInfo, + cardinalityInfo: OwlCardinality.KnoraCardinalityInfo, internalClassIri: SmartIri, internalOntologyIri: SmartIri )(implicit ec: ExecutionContext): Future[Boolean] = { diff --git a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpers.scala b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpers.scala index de1c0fb0ee..44cc99d387 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpers.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpers.scala @@ -11,6 +11,7 @@ import akka.pattern._ import akka.util.Timeout import dsp.constants.SalsahGui import dsp.errors._ +import dsp.schema.domain.Cardinality._ import org.knora.webapi.ApiV2Complex import org.knora.webapi.ApiV2Schema import org.knora.webapi.ApiV2Simple @@ -26,7 +27,7 @@ import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.messages.util.ErrorHandlingMap import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.util.rdf.VariableResultsRow -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.messages.v2.responder.standoffmessages.StandoffDataTypeClasses import org.knora.webapi.responders.v2.ontology.Cache.OntologyCacheData @@ -650,7 +651,7 @@ object OntologyHelpers { ) propertyObjectClassConstraint == OntologyConstants.KnoraBase.BooleanValue.toSmartIri && - !(knoraCardinalityInfo.cardinality == Cardinality.MustHaveOne || knoraCardinalityInfo.cardinality == Cardinality.MayHaveOne) + !(knoraCardinalityInfo.cardinality == MustHaveOne || knoraCardinalityInfo.cardinality == MayHaveOne) }.keySet if (invalidCardinalitiesOnBooleanProps.nonEmpty) { @@ -856,16 +857,10 @@ object OntologyHelpers { directCardinalities = internalClassDef.directCardinalities ++ linkValuePropCardinalitiesToAdd ) - // 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). + // Determine the strictest cardinality the class inherits. If the ontology of the base class can't be found, it's assumed to be an external ontology (p.ex. foaf). cardinalitiesAvailableToInherit: Map[SmartIri, KnoraCardinalityInfo] = - 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 + getStrictestCardinalitiesFromClasses(classDefWithAddedLinkValueProps.subClassOf, cacheData) // Check that the cardinalities directly defined on the class are compatible with any inheritable // cardinalities, and let directly-defined cardinalities override cardinalities in base classes. @@ -954,6 +949,50 @@ object OntologyHelpers { } yield (classDefWithAddedLinkValueProps, cardinalitiesForClassWithInheritance) } + /** + * Given a set of class IRIs, determines the strictest cardinality for each referenced property. It is possible that the strictest + * cardinality is stricter than all the used ones. + * This method is used to check if an inherited property of a class uses a cardinality that is compatible with the cardinalities + * of the class' super class. + * + * @param classes the set of class IRIs. + * @param cacheData the ontology cache data. It is needed to get the class definitions from the cache + * @return a map with the property IRIs and their respective cardinality definitions + */ + def getStrictestCardinalitiesFromClasses( + classes: Set[SmartIri], + cacheData: OntologyCacheData + ): Map[SmartIri, KnoraCardinalityInfo] = + classes.foldLeft(Map[SmartIri, KnoraCardinalityInfo]()) { + (acc: Map[SmartIri, KnoraCardinalityInfo], baseClassIri: SmartIri) => + val ontology = cacheData.ontologies.getOrElse(baseClassIri.getOntologyFromEntity, None) + val cardinalitiesOfBaseClass: List[(SmartIri, KnoraCardinalityInfo)] = ontology match { + case ontology: ReadOntologyV2 => ontology.classes(baseClassIri).allCardinalities.toList + case _ => List.empty + } + + val additionalCardinalities = cardinalitiesOfBaseClass.map { case (iri, nextBaseClassCardinality) => + // if there are multiple instances of the same property the class gets from inheritance, keep only the strictest one + acc.get(iri) match { + // if the previous base class cardinality is stricter than the next base class cardinality, keep the previous + case Some(previousCardinality) + if previousCardinality.cardinality.isStricterThan(nextBaseClassCardinality.cardinality) => + (iri, previousCardinality) + // if the previous base class cardinality is "1-n" or "0-1" and the next base class cardinality is also "1-n" or "0-1", update the + // accumulator with cardinality of "1", because only this is stricter than both + case Some(previousCardinality) + if ( + (nextBaseClassCardinality.cardinality == MustHaveSome || nextBaseClassCardinality.cardinality == MayHaveOne) && + (previousCardinality.cardinality == MustHaveSome || previousCardinality.cardinality == MayHaveOne) + ) => + (iri, KnoraCardinalityInfo(MustHaveOne, previousCardinality.guiOrder)) + // in all other cases, keep the next base class cardinality + case _ => (iri, nextBaseClassCardinality) + } + }.toMap + acc ++ additionalCardinalities + } + /** * Given a set of property IRIs, determines whether the set contains a property P and a subproperty of P. * @@ -1635,9 +1674,9 @@ object OntologyHelpers { ) } - propertyIri -> Cardinality.owlCardinality2KnoraCardinality( + propertyIri -> owlCardinality2KnoraCardinality( propertyIri = propertyIri.toString, - owlCardinality = Cardinality.OwlCardinalityInfo( + owlCardinality = OwlCardinalityInfo( owlCardinalityIri = owlCardinalityIri.toString, owlCardinalityValue = owlCardinalityValue, guiOrder = guiOrder @@ -1927,16 +1966,11 @@ object OntologyHelpers { if (thisClassProp == baseClassProp || basePropsOfThisClassProp.contains(baseClassProp)) { // Yes. Is the directly defined one at least as restrictive as the inheritable one? - if ( - !Cardinality.isCompatible( - directCardinality = thisClassCardinality.cardinality, - inheritableCardinality = baseClassCardinality.cardinality - ) - ) { + if (baseClassCardinality.cardinality.isStricterThan(thisClassCardinality.cardinality)) { // No. Throw an exception. errorFun( - s"In class <${classIri.toOntologySchema(errorSchema)}>, the directly defined cardinality ${thisClassCardinality.cardinality} on ${thisClassProp - .toOntologySchema(errorSchema)} is not compatible with the inherited cardinality ${baseClassCardinality.cardinality} on ${baseClassProp + s"In class <${classIri.toOntologySchema(errorSchema)}>, the directly defined cardinality '${thisClassCardinality.cardinality.value}' on ${thisClassProp + .toOntologySchema(errorSchema)} is not compatible with the inherited or allowed cardinality '${baseClassCardinality.cardinality.value}' on ${baseClassProp .toOntologySchema(errorSchema)}, because it is less restrictive" ) } else { @@ -1981,9 +2015,7 @@ object OntologyHelpers { if (thisClassProps.size > 1) { val overriddenCardinality: KnoraCardinalityInfo = inheritableCardinalities(baseClassProp) - if ( - overriddenCardinality.cardinality == Cardinality.MustHaveOne || overriddenCardinality.cardinality == Cardinality.MayHaveOne - ) { + if (overriddenCardinality.cardinality == MustHaveOne || overriddenCardinality.cardinality == MayHaveOne) { errorFun( s"In class <${classIri.toOntologySchema(errorSchema)}>, there is more than one cardinality that would override the inherited cardinality $overriddenCardinality on <${baseClassProp .toOntologySchema(errorSchema)}>" diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/addCardinalitiesToClass.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/addCardinalitiesToClass.scala.txt index 43f64a3e19..c3a6798bd9 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/addCardinalitiesToClass.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/addCardinalitiesToClass.scala.txt @@ -6,7 +6,7 @@ @import org.knora.webapi._ @import org.knora.webapi.messages.SmartIri @import org.knora.webapi.messages.v2.responder.ontologymessages._ -@import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality._ +@import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ @import java.time.Instant @* @@ -43,7 +43,7 @@ DELETE { @for((propertyIri, knoraCardinality) <- cardinalitiesToAdd) { - @defining(Cardinality.knoraCardinality2OwlCardinality(knoraCardinality)) { owlCardinalityInfo => + @defining(OwlCardinality.knoraCardinality2OwlCardinality(knoraCardinality)) { owlCardinalityInfo => ?class rdfs:subClassOf [ rdf:type owl:Restriction ; owl:onProperty <@propertyIri> ; diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/createClass.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/createClass.scala.txt index 33dcd562d9..6a5ffc736b 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/createClass.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/createClass.scala.txt @@ -6,7 +6,7 @@ @import org.knora.webapi._ @import org.knora.webapi.messages.SmartIri @import org.knora.webapi.messages.v2.responder.ontologymessages._ -@import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality._ +@import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ @import org.knora.webapi.messages.store.triplestoremessages._ @import java.time.Instant @@ -57,7 +57,7 @@ DELETE { @for((propertyIri, knoraCardinality) <- classDef.directCardinalities) { - @defining(Cardinality.knoraCardinality2OwlCardinality(knoraCardinality)) { owlCardinalityInfo => + @defining(knoraCardinality2OwlCardinality(knoraCardinality)) { owlCardinalityInfo => <@classDef.classIri> rdfs:subClassOf [ rdf:type owl:Restriction ; owl:onProperty <@propertyIri> ; diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/replaceClassCardinalities.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/replaceClassCardinalities.scala.txt index c8b2daac7e..6f57988ae3 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/replaceClassCardinalities.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/v2/replaceClassCardinalities.scala.txt @@ -6,7 +6,7 @@ @import org.knora.webapi._ @import org.knora.webapi.messages.SmartIri @import org.knora.webapi.messages.v2.responder.ontologymessages._ -@import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality._ +@import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ @import java.time.Instant @* @@ -64,7 +64,7 @@ INSERT { GRAPH <@ontologyNamedGraphIri> { @for((propertyIri, knoraCardinality) <- newCardinalities) { - @defining(Cardinality.knoraCardinality2OwlCardinality(knoraCardinality)) { owlCardinalityInfo => + @defining(OwlCardinality.knoraCardinality2OwlCardinality(knoraCardinality)) { owlCardinalityInfo => <@classIri> rdfs:subClassOf [ rdf:type owl:Restriction ; owl:onProperty <@propertyIri> ; diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/xsd/v1/xmlImport.scala.xml b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/xsd/v1/xmlImport.scala.xml index a4213afe77..21169a9b69 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/xsd/v1/xmlImport.scala.xml +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/xsd/v1/xmlImport.scala.xml @@ -6,9 +6,10 @@ @import org.knora.webapi._ @import dsp.errors.{AssertionException, InconsistentRepositoryDataException, SparqlGenerationException} @import org.knora.webapi.messages.v1.responder.ontologymessages._ -@import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality +@import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality @import org.knora.webapi.messages.OntologyConstants @import org.knora.webapi.messages.StringFormatter.XmlImportNamespaceInfoV1 +@import dsp.schema.domain.Cardinality._ @** * Generates an XML schema based on ontology definitions. @@ -35,11 +36,10 @@ * SPDX-License-Identifier: Apache-2.0 --> + xmlns="@{targetNamespaceInfo.namespace}" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + @for(namespaceInfo <- importedNamespaces) { xmlns:@{namespaceInfo.prefixLabel}="@{namespaceInfo.namespace}" + } xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.0"> @for(namespaceInfo <- importedNamespaces) { } @@ -48,15 +48,15 @@ @defining(getEntityName(resourceClassIri)) { resourceClassName => - - - - - - + + + + + + @if(resourceClassInfo.fileValueProperties.nonEmpty) { - + } @for((propertyIri, cardinalityInfo) <- resourceClassInfo.knoraResourceCardinalities.toVector.sortBy(_._1)) { @@ -69,40 +69,28 @@ @defining(getNamespacePrefixLabel(propertyIri)) { propertyNamespacePrefixLabel => - @if(propertyNamespacePrefixLabel == targetNamespaceInfo.prefixLabel) { + @if(propertyNamespacePrefixLabel == targetNamespaceInfo.prefixLabel) { name="@{getEntityName(propertyIri)}" - name="@{getEntityName(propertyIri)}" - - } else { - - name="@{propertyNamespacePrefixLabel}__@{getEntityName(propertyIri)}" + } else { name="@{propertyNamespacePrefixLabel}__@{getEntityName(propertyIri)}" } } @cardinalityInfo.cardinality match { - case Cardinality.MayHaveOne => { - - minOccurs="0" maxOccurs="1" + case MayHaveOne => { minOccurs="0" maxOccurs="1" } - case Cardinality.MayHaveMany => { - - minOccurs="0" maxOccurs="unbounded" + case MayHaveMany => { minOccurs="0" maxOccurs="unbounded" } - case Cardinality.MustHaveOne => { - - minOccurs="1" maxOccurs="1" + case MustHaveOne => { minOccurs="1" maxOccurs="1" } - case Cardinality.MustHaveSome => { - - minOccurs="1" maxOccurs="unbounded" + case MustHaveSome => { minOccurs="1" maxOccurs="unbounded" } } @@ -113,13 +101,9 @@ @defining(getNamespacePrefixLabel(propertyObjectClassConstraint)) { targetResourceClassNamespacePrefixLabel => - @if(targetResourceClassNamespacePrefixLabel == targetNamespaceInfo.prefixLabel) { - - type="@{getEntityName(propertyObjectClassConstraint)}_linkValueType" + @if(targetResourceClassNamespacePrefixLabel == targetNamespaceInfo.prefixLabel) { type="@{getEntityName(propertyObjectClassConstraint)}_linkValueType" - } else { - - type="@{targetResourceClassNamespacePrefixLabel}:@{getEntityName(propertyObjectClassConstraint)}_linkValueType" + } else { type="@{targetResourceClassNamespacePrefixLabel}:@{getEntityName(propertyObjectClassConstraint)}_linkValueType" } @@ -129,75 +113,51 @@ @propertyObjectClassConstraint match { - case OntologyConstants.KnoraBase.TextValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:richtextValueType" + case OntologyConstants.KnoraBase.TextValue => { type="@{knoraXmlImportNamespacePrefixLabel}:richtextValueType" } - case OntologyConstants.KnoraBase.IntValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:intValueType" + case OntologyConstants.KnoraBase.IntValue => { type="@{knoraXmlImportNamespacePrefixLabel}:intValueType" } - case OntologyConstants.KnoraBase.BooleanValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:booleanValueType" + case OntologyConstants.KnoraBase.BooleanValue => { type="@{knoraXmlImportNamespacePrefixLabel}:booleanValueType" } - case OntologyConstants.KnoraBase.UriValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:uriValueType" + case OntologyConstants.KnoraBase.UriValue => { type="@{knoraXmlImportNamespacePrefixLabel}:uriValueType" } - case OntologyConstants.KnoraBase.DecimalValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:decimalValueType" + case OntologyConstants.KnoraBase.DecimalValue => { type="@{knoraXmlImportNamespacePrefixLabel}:decimalValueType" } - case OntologyConstants.KnoraBase.DateValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:dateValueType" + case OntologyConstants.KnoraBase.DateValue => { type="@{knoraXmlImportNamespacePrefixLabel}:dateValueType" } - case OntologyConstants.KnoraBase.ColorValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:colorValueType" + case OntologyConstants.KnoraBase.ColorValue => { type="@{knoraXmlImportNamespacePrefixLabel}:colorValueType" } - case OntologyConstants.KnoraBase.GeomValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:geomValueType" + case OntologyConstants.KnoraBase.GeomValue => { type="@{knoraXmlImportNamespacePrefixLabel}:geomValueType" } - case OntologyConstants.KnoraBase.ListValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:hlistValueType" + case OntologyConstants.KnoraBase.ListValue => { type="@{knoraXmlImportNamespacePrefixLabel}:hlistValueType" } - case OntologyConstants.KnoraBase.IntervalValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:intervalValueType" + case OntologyConstants.KnoraBase.IntervalValue => { type="@{knoraXmlImportNamespacePrefixLabel}:intervalValueType" } - case OntologyConstants.KnoraBase.TimeValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:timeValueType" + case OntologyConstants.KnoraBase.TimeValue => { type="@{knoraXmlImportNamespacePrefixLabel}:timeValueType" } - case OntologyConstants.KnoraBase.GeonameValue => { - - type="@{knoraXmlImportNamespacePrefixLabel}:geonameValueType" + case OntologyConstants.KnoraBase.GeonameValue => { type="@{knoraXmlImportNamespacePrefixLabel}:geonameValueType" } @@ -222,12 +182,12 @@ } - - - - + + + + - + @@ -237,4 +197,4 @@ } - + diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/InstanceChecker.scala b/webapi/src/test/scala/org/knora/webapi/e2e/InstanceChecker.scala index 25192890ea..231a5da3e7 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/InstanceChecker.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/InstanceChecker.scala @@ -6,15 +6,17 @@ package org.knora.webapi.e2e import com.typesafe.scalalogging.LazyLogging -import org.knora.webapi._ import dsp.errors.AssertionException +import dsp.schema.domain.Cardinality +import dsp.schema.domain.Cardinality._ +import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.util._ import org.knora.webapi.messages.util.rdf._ -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality._ +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages._ import java.net.URLEncoder @@ -138,7 +140,7 @@ class InstanceChecker(instanceInspector: InstanceInspector) extends LazyLogging (cardinality == MustHaveSome && numberOfObjects == 0) ) { throwAndLogAssertionException( - s"Property $instancePropertyName has $numberOfObjects objects, but its cardinality is $cardinality" + s"Property $instancePropertyName has $numberOfObjects objects, but its cardinality is ${cardinality.value}" ) } } diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala index 6c4c060b71..745cfa298b 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/v2/OntologyV2R2RSpec.scala @@ -7,6 +7,7 @@ import akka.http.scaladsl.model.headers.BasicHttpCredentials import akka.http.scaladsl.testkit.RouteTestTimeout import dsp.constants.SalsahGui import dsp.errors.AssertionException +import dsp.schema.domain.Cardinality._ import dsp.valueobjects.LangString import dsp.valueobjects.LanguageCode import org.knora.webapi._ @@ -20,8 +21,8 @@ import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject import org.knora.webapi.messages.util.rdf._ -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality import org.knora.webapi.messages.v2.responder.ontologymessages.InputOntologyV2 +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality import org.knora.webapi.messages.v2.responder.ontologymessages.TestResponseParsingModeV2 import org.knora.webapi.models._ import org.knora.webapi.routing.v2.OntologiesRouteV2 @@ -3750,7 +3751,7 @@ class OntologyV2R2RSpec extends R2RSpec { .directCardinalities assert(videoSequenceCardinalities.keySet.contains(isSequenceOfVideoPropertyIri)) val cardinality = videoSequenceCardinalities.get(isSequenceOfVideoPropertyIri).get.cardinality - assert(cardinality == Cardinality.MustHaveOne) + assert(cardinality == MustHaveOne) } } @@ -3885,7 +3886,7 @@ class OntologyV2R2RSpec extends R2RSpec { .directCardinalities assert(audioSequenceCardinalities.keySet.contains(isSequenceOfAudioPropertyIri)) val cardinality = audioSequenceCardinalities.get(isSequenceOfAudioPropertyIri).get.cardinality - assert(cardinality == Cardinality.MustHaveOne) + assert(cardinality == MustHaveOne) } } "not create a property with invalid gui attribute" in { diff --git a/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/InputOntologyV2Spec.scala b/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/InputOntologyV2Spec.scala index 7c04c8f10d..7f39fea9c5 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/InputOntologyV2Spec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/InputOntologyV2Spec.scala @@ -5,15 +5,16 @@ package org.knora.webapi.messages.v2.responder.ontologymessages +import dsp.errors.BadRequestException +import dsp.schema.domain.Cardinality._ import org.knora.webapi.ApiV2Complex import org.knora.webapi.CoreSpec -import dsp.errors.BadRequestException import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.store.triplestoremessages.SmartIriLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.rdf.JsonLDUtil -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo import java.time.Instant @@ -244,7 +245,7 @@ object InputOntologyV2Spec { ontologySchema = ApiV2Complex, directCardinalities = Map( "http://0.0.0.0:3333/ontology/0001/anything/v2#hasName".toSmartIri -> KnoraCardinalityInfo( - Cardinality.MayHaveOne + MayHaveOne ) ), subClassOf = Set("http://0.0.0.0:3333/ontology/0001/anything/v2#Thing".toSmartIri) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraCardinalityInfoIsStricterThanZSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraCardinalityInfoIsStricterThanZSpec.scala new file mode 100644 index 0000000000..f651d82bc6 --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraCardinalityInfoIsStricterThanZSpec.scala @@ -0,0 +1,82 @@ +/* + * Copyright © 2021 - 2022 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.v2.responder.ontologymessages + +import dsp.schema.domain.Cardinality._ +import zio.test._ + +/** + * Tests the comparison forstrictness of cardinalities with [[isStricterThan()]]. + */ +object KnoraCardinalityInfoIsStricterThanZSpec extends ZIOSpecDefault { + + def spec = (mustHaveOneTest + mustHaveSomeTest + mayHaveOneTest + mayHaveManyTest) + + val mustHaveOne = MustHaveOne // "1" + val mustHaveSome = MustHaveSome // "1-n" + val mayHaveOne = MayHaveOne // "0-1" + val mayHaveMany = MayHaveMany // "0-n" + + val mustHaveOneTest = suite("MustHaveOneTest")( + test("cardinality of '1' is NOT stricter than cardinality of '1'") { + assertTrue(!mustHaveOne.isStricterThan(mustHaveOne)) + }, + test("cardinality of '1' is stricter than cardinality of '1-n'") { + assertTrue(mustHaveOne.isStricterThan(mustHaveSome)) + }, + test("cardinality of '1' is stricter than cardinality of '0-1'") { + assertTrue(mustHaveOne.isStricterThan(mayHaveOne)) + }, + test("cardinality of '1' is stricter than cardinality of '0-n'") { + assertTrue(mustHaveOne.isStricterThan(mayHaveMany)) + } + ) + + val mustHaveSomeTest = suite("MustHaveSomeTest")( + test("cardinality of '1-n' is NOT stricter than cardinality of '1'") { + assertTrue(!mustHaveSome.isStricterThan(mustHaveOne)) + }, + test("cardinality of '1-n' is NOT stricter than cardinality of '1-n'") { + assertTrue(!mustHaveSome.isStricterThan(mustHaveSome)) + }, + test("cardinality of '1-n' is NOT stricter than cardinality of '0-1'") { + assertTrue(!mustHaveSome.isStricterThan(mayHaveOne)) + }, + test("cardinality of '1-n' is stricter than cardinality of '0-n'") { + assertTrue(mustHaveSome.isStricterThan(mayHaveMany)) + } + ) + + val mayHaveOneTest = suite("MayHaveOneTest")( + test("cardinality of '0-1' is NOT stricter than cardinality of '1'") { + assertTrue(!mayHaveOne.isStricterThan(mustHaveOne)) + }, + test("cardinality of '0-1' is NOT stricter than cardinality of '1-n'") { + assertTrue(!mayHaveOne.isStricterThan(mustHaveSome)) + }, + test("cardinality of '0-1' is NOT stricter than cardinality of '0-1'") { + assertTrue(!mayHaveOne.isStricterThan(mayHaveOne)) + }, + test("cardinality of '0-1' is stricter than cardinality of '0-n'") { + assertTrue(mayHaveOne.isStricterThan(mayHaveMany)) + } + ) + + val mayHaveManyTest = suite("MayHaveManyTest")( + test("cardinality of '0-n' is NOT stricter than cardinality of '1'") { + assertTrue(!mayHaveMany.isStricterThan(mustHaveOne)) + }, + test("cardinality of '0-n' is NOT stricter than cardinality of '1-n'") { + assertTrue(!mayHaveMany.isStricterThan(mustHaveSome)) + }, + test("cardinality of '0-n' is NOT stricter than cardinality of '0-1'") { + assertTrue(!mayHaveMany.isStricterThan(mayHaveOne)) + }, + test("cardinality of '0-n' is NOT stricter than cardinality of '0-n'") { + assertTrue(!mayHaveMany.isStricterThan(mayHaveMany)) + } + ) +} diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala index d45cc3b765..7ff51bad50 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala @@ -6,8 +6,12 @@ package org.knora.webapi.responders.v2 import akka.testkit.ImplicitSender -import org.knora.webapi._ +import dsp.constants.SalsahGui import dsp.errors._ +import dsp.schema.domain.Cardinality._ +import dsp.valueobjects.Iri +import dsp.valueobjects.Schema +import org.knora.webapi._ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.OntologyConstants import org.knora.webapi.messages.SmartIri @@ -17,7 +21,7 @@ import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.v2.responder.CanDoResponseV2 import org.knora.webapi.messages.v2.responder.SuccessResponseV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality.KnoraCardinalityInfo +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo import org.knora.webapi.messages.v2.responder.ontologymessages._ import org.knora.webapi.messages.v2.responder.resourcemessages.CreateResourceRequestV2 import org.knora.webapi.messages.v2.responder.resourcemessages.CreateResourceV2 @@ -31,9 +35,6 @@ import java.time.Instant import java.util.UUID import scala.concurrent.duration._ import scala.language.postfixOps -import dsp.valueobjects.Iri -import dsp.valueobjects.Schema -import dsp.constants.SalsahGui /** * Tests [[OntologyResponderV2]]. @@ -1091,7 +1092,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ontologySchema = ApiV2Complex, directCardinalities = Map( "http://0.0.0.0:3333/ontology/0001/freetest/v2#hasComicAuthor".toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ) ) ), @@ -2400,9 +2401,9 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne), + AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne), AnythingOntologyIri.makeEntityIri("hasInteger") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(20) ) ), @@ -2444,9 +2445,9 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasOtherThing") -> KnoraCardinalityInfo(Cardinality.MustHaveOne), + AnythingOntologyIri.makeEntityIri("hasOtherThing") -> KnoraCardinalityInfo(MustHaveOne), AnythingOntologyIri.makeEntityIri("hasBlueThing") -> KnoraCardinalityInfo( - cardinality = Cardinality.MustHaveOne + cardinality = MustHaveOne ) ), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), @@ -2487,7 +2488,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasInterestingThingValue") -> KnoraCardinalityInfo(Cardinality.MayHaveOne) + AnythingOntologyIri.makeEntityIri("hasInterestingThingValue") -> KnoraCardinalityInfo(MayHaveOne) ), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex @@ -2526,7 +2527,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasInterestingThing") -> KnoraCardinalityInfo(Cardinality.MayHaveOne) + AnythingOntologyIri.makeEntityIri("hasInterestingThing") -> KnoraCardinalityInfo(MayHaveOne) ), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex @@ -2796,9 +2797,9 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne), + AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne), AnythingOntologyIri.makeEntityIri("hasInteger") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(20) ) ), @@ -2886,7 +2887,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne) + AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne) ), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex @@ -2967,7 +2968,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasInteger") -> KnoraCardinalityInfo(Cardinality.MayHaveOne) + AnythingOntologyIri.makeEntityIri("hasInteger") -> KnoraCardinalityInfo(MayHaveOne) ), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex @@ -3005,7 +3006,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne) + AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne) ), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex @@ -3086,7 +3087,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne) + AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne) ), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex @@ -3539,7 +3540,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = - Map(AnythingOntologyIri.makeEntityIri("nonexistentProperty") -> KnoraCardinalityInfo(Cardinality.MayHaveOne)), + Map(AnythingOntologyIri.makeEntityIri("nonexistentProperty") -> KnoraCardinalityInfo(MayHaveOne)), subClassOf = Set(OntologyConstants.KnoraApiV2Complex.Resource.toSmartIri), ontologySchema = ApiV2Complex ) @@ -3580,8 +3581,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ) ), - directCardinalities = - Map(AnythingOntologyIri.makeEntityIri("hasInteger") -> KnoraCardinalityInfo(Cardinality.MayHaveOne)), + directCardinalities = Map(AnythingOntologyIri.makeEntityIri("hasInteger") -> KnoraCardinalityInfo(MayHaveOne)), subClassOf = Set(OntologyConstants.KnoraApiV2Complex.Resource.toSmartIri), ontologySchema = ApiV2Complex ) @@ -3622,8 +3622,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ) ), - directCardinalities = - Map(AnythingOntologyIri.makeEntityIri("hasBoolean") -> KnoraCardinalityInfo(Cardinality.MustHaveOne)), + directCardinalities = Map(AnythingOntologyIri.makeEntityIri("hasBoolean") -> KnoraCardinalityInfo(MustHaveOne)), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex ) @@ -3641,7 +3640,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { val readClassInfo = externalOntology.classes(classIri) readClassInfo.entityInfoContent should ===(classInfoContent) readClassInfo.allCardinalities(AnythingOntologyIri.makeEntityIri("hasBoolean")).cardinality should ===( - Cardinality.MustHaveOne + MustHaveOne ) val metadata = externalOntology.ontologyMetadata @@ -3676,8 +3675,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ) ), - directCardinalities = - Map(AnythingOntologyIri.makeEntityIri("hasBoolean") -> KnoraCardinalityInfo(Cardinality.MayHaveMany)), + directCardinalities = Map(AnythingOntologyIri.makeEntityIri("hasBoolean") -> KnoraCardinalityInfo(MayHaveMany)), subClassOf = Set(AnythingOntologyIri.makeEntityIri("Thing")), ontologySchema = ApiV2Complex ) @@ -4111,7 +4109,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo(Cardinality.MustHaveOne) + AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo(MustHaveOne) ), ontologySchema = ApiV2Complex ) @@ -4203,7 +4201,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ), @@ -4285,7 +4283,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - propertyIri -> KnoraCardinalityInfo(cardinality = Cardinality.MayHaveOne, guiOrder = Some(0)) + propertyIri -> KnoraCardinalityInfo(cardinality = MayHaveOne, guiOrder = Some(0)) ), ontologySchema = ApiV2Complex ) @@ -4298,9 +4296,9 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) val expectedDirectCardinalities = Map( - propertyIri -> KnoraCardinalityInfo(cardinality = Cardinality.MayHaveOne, guiOrder = Some(0)), + propertyIri -> KnoraCardinalityInfo(cardinality = MayHaveOne, guiOrder = Some(0)), propertyIri.fromLinkPropToLinkValueProp -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ) @@ -4347,7 +4345,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveMany, + cardinality = MayHaveMany, guiOrder = Some(0) ) ), @@ -4379,7 +4377,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ), @@ -4395,15 +4393,15 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { val expectedDirectCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasOtherNothing") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ), AnythingOntologyIri.makeEntityIri("hasOtherNothingValue") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ), AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ) @@ -4444,7 +4442,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MustHaveSome) + AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MustHaveSome) ), ontologySchema = ApiV2Complex ) @@ -4474,7 +4472,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ) ), directCardinalities = Map( - AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne) + AnythingOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne) ), ontologySchema = ApiV2Complex ) @@ -4571,7 +4569,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasEmptiness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(1) ) ), @@ -4587,19 +4585,19 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { val expectedDirectCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasOtherNothing") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ), AnythingOntologyIri.makeEntityIri("hasOtherNothingValue") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ), AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ), AnythingOntologyIri.makeEntityIri("hasEmptiness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(1) ) ) @@ -4643,7 +4641,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasEmptiness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ), @@ -4676,15 +4674,15 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasOtherNothing") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(1) ), AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(2) ), AnythingOntologyIri.makeEntityIri("hasEmptiness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(3) ) ), @@ -4700,19 +4698,19 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { val expectedCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasOtherNothing") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(1) ), AnythingOntologyIri.makeEntityIri("hasOtherNothingValue") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(1) ), AnythingOntologyIri.makeEntityIri("hasNothingness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(2) ), AnythingOntologyIri.makeEntityIri("hasEmptiness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(3) ) ) @@ -4745,7 +4743,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( AnythingOntologyIri.makeEntityIri("hasEmptiness") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ), @@ -5060,7 +5058,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), subClassOf = Set(OntologyConstants.KnoraApiV2Complex.Resource.toSmartIri), directCardinalities = - Map(IncunabulaOntologyIri.makeEntityIri("description") -> KnoraCardinalityInfo(Cardinality.MayHaveOne)), + Map(IncunabulaOntologyIri.makeEntityIri("description") -> KnoraCardinalityInfo(MayHaveOne)), ontologySchema = ApiV2Complex ) @@ -5303,7 +5301,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), subClassOf = Set(ExampleSharedOntologyIri.makeEntityIri("Box")), directCardinalities = - Map(ExampleSharedOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne)), + Map(ExampleSharedOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne)), ontologySchema = ApiV2Complex ) @@ -5781,13 +5779,13 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ontologySchema = ApiV2Complex, directCardinalities = Map( (anythingOntology + "testTextProp").toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ), (anythingOntology + "testIntProp").toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ), (anythingOntology + "testLinkProp").toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ) ) ), @@ -5817,10 +5815,10 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ontologySchema = ApiV2Complex, directCardinalities = Map( (anythingOntology + "testTextProp").toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ), (anythingOntology + "testIntProp").toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ) ) ), @@ -6030,10 +6028,10 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ontologySchema = ApiV2Complex, directCardinalities = Map( "http://0.0.0.0:3333/ontology/0001/freetest/v2#hasBlueTestTextProp".toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ), "http://0.0.0.0:3333/ontology/0001/freetest/v2#hasBlueTestIntProp".toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ) ) ), @@ -6096,7 +6094,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ontologySchema = ApiV2Complex, directCardinalities = Map( "http://0.0.0.0:3333/ontology/0001/freetest/v2#hasBlueTestTextProp".toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ) ) ), @@ -6123,7 +6121,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ontologySchema = ApiV2Complex, directCardinalities = Map( "http://0.0.0.0:3333/ontology/0001/freetest/v2#hasBlueTestTextProp".toSmartIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ) ) ), @@ -6187,7 +6185,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { "http://xmlns.com/foaf/0.1/Person".toSmartIri ), directCardinalities = - Map(ExampleSharedOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(Cardinality.MayHaveOne)), + Map(ExampleSharedOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo(MayHaveOne)), ontologySchema = ApiV2Complex ) @@ -6311,7 +6309,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( propertyIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ), @@ -6328,11 +6326,11 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { // check if cardinality was added correctly val expectedDirectCardinalities: Map[SmartIri, KnoraCardinalityInfo] = Map( propertyIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ), ExampleSharedOntologyIri.makeEntityIri("hasName") -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne + cardinality = MayHaveOne ) ) @@ -6377,7 +6375,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { ), directCardinalities = Map( propertyIri -> KnoraCardinalityInfo( - cardinality = Cardinality.MayHaveOne, + cardinality = MayHaveOne, guiOrder = Some(0) ) ), @@ -6439,7 +6437,7 @@ class OntologyResponderV2Spec extends CoreSpec() with ImplicitSender { "change the GUI order of a cardinality in a base class, and update its subclass in the ontology cache" in { val classIri = AnythingOntologyIri.makeEntityIri("Thing") - val newCardinality = KnoraCardinalityInfo(cardinality = Cardinality.MayHaveMany, guiOrder = Some(100)) + val newCardinality = KnoraCardinalityInfo(cardinality = MayHaveMany, guiOrder = Some(100)) val classInfoContent = ClassInfoContentV2( classIri = classIri, diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/AddCardinalitiesToClassSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/AddCardinalitiesToClassSpec.scala index 20994ef135..0c87ae8a2d 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/AddCardinalitiesToClassSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/AddCardinalitiesToClassSpec.scala @@ -6,6 +6,7 @@ package org.knora.webapi.responders.v2.ontology import akka.util.Timeout +import dsp.schema.domain.Cardinality.MayHaveOne import org.knora.webapi.ApiV2Complex import org.knora.webapi.CoreSpec import org.knora.webapi.messages.IriConversions._ @@ -17,10 +18,10 @@ import org.knora.webapi.messages.store.triplestoremessages.SmartIriLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.SparqlSelectRequest import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.v2.responder.ontologymessages.AddCardinalitiesToClassRequestV2 -import org.knora.webapi.messages.v2.responder.ontologymessages.Cardinality import org.knora.webapi.messages.v2.responder.ontologymessages.ClassInfoContentV2 import org.knora.webapi.messages.v2.responder.ontologymessages.ClassesGetRequestV2 import org.knora.webapi.messages.v2.responder.ontologymessages.OntologyMetadataGetByIriRequestV2 +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality._ import org.knora.webapi.messages.v2.responder.ontologymessages.PredicateInfoV2 import org.knora.webapi.messages.v2.responder.ontologymessages.ReadOntologyMetadataV2 import org.knora.webapi.messages.v2.responder.ontologymessages.ReadOntologyV2 @@ -91,8 +92,7 @@ class AddCardinalitiesToClassSpec extends CoreSpec { objects = Vector(SmartIriLiteralV2(value = OntologyConstants.Owl.Class.toSmartIri)) ) ), - directCardinalities = - Map(newPropertyIri -> Cardinality.KnoraCardinalityInfo(cardinality = Cardinality.MayHaveOne)) + directCardinalities = Map(newPropertyIri -> KnoraCardinalityInfo(cardinality = MayHaveOne)) ), lastModificationDate = ontologyLastModificationDate, apiRequestID = UUID.randomUUID, diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala index a3bd6314cb..4cadaedab2 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/DeleteCardinalitiesFromClassSpec.scala @@ -12,6 +12,7 @@ import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject import org.knora.webapi.settings.KnoraDispatchers +import org.knora.webapi.responders.v2.ontology.CardinalityHandler import akka.util.Timeout /** @@ -31,7 +32,7 @@ class DeleteCardinalitiesFromClassSpec extends CoreSpec { val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTest").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) + val resF = CardinalityHandler.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) resF map { res => println(res); assert(res, "property is used in resource (instance of that resource class)") } } @@ -40,7 +41,7 @@ class DeleteCardinalitiesFromClassSpec extends CoreSpec { val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTestResourceClass").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) + val resF = CardinalityHandler.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) resF map { res => println(res); assert(!res, "property is not used in resource (instance of that resource class)") } @@ -51,7 +52,7 @@ class DeleteCardinalitiesFromClassSpec extends CoreSpec { val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTest").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) + val resF = CardinalityHandler.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) resF map { res => println(res); assert(!res, "property is not used in resource (instance of that resource class)") } @@ -63,7 +64,7 @@ class DeleteCardinalitiesFromClassSpec extends CoreSpec { val internalClassIri = anythingOntologyIri.makeEntityIri("Thing").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) + val resF = CardinalityHandler.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) resF map { res => println(res); assert(res, "property is used in resource (instance of resource class)") } } @@ -72,7 +73,7 @@ class DeleteCardinalitiesFromClassSpec extends CoreSpec { val internalClassIri = freetestOntologyIri.makeEntityIri("FreeTest").toOntologySchema(InternalSchema) println(s"internalPropertyIri: $internalPropertyIri") - val resF = Cardinalities.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) + val resF = CardinalityHandler.isPropertyUsedInResources(settings, appActor, internalClassIri, internalPropertyIri) resF map { res => println(res); assert(res, "property is used in a resource of subclass") } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpersSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpersSpec.scala new file mode 100644 index 0000000000..09a992a301 --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/ontology/OntologyHelpersSpec.scala @@ -0,0 +1,85 @@ +/* + * Copyright © 2021 - 2022 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.responders.v2.ontology + +import dsp.schema.domain.Cardinality +import dsp.schema.domain.Cardinality._ +import org.knora.webapi.CoreSpec +import org.knora.webapi.InternalSchema +import org.knora.webapi.messages.IriConversions._ +import org.knora.webapi.messages.SmartIri +import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject +import org.knora.webapi.messages.v2.responder.ontologymessages.OwlCardinality.KnoraCardinalityInfo +import org.knora.webapi.responders.v2.ontology.Cache._ + +import scala.concurrent.Await +import scala.concurrent.Future +import scala.concurrent.duration._ + +/** + * This spec is used to test [[org.knora.webapi.responders.v2.ontology.OntologyHelpers]]. + */ +class OntologyHelpersSpec extends CoreSpec { + + private implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance + private implicit val timeout = 10.seconds + private val freeTestOntology = RdfDataObject( + path = "test_data/ontologies/freetest-onto.ttl", + name = "http://www.knora.org/ontology/0001/freetest" + ) + override lazy val rdfDataObjects: List[RdfDataObject] = List(freeTestOntology) + + val freetestOntologyIri: SmartIri = + "http://0.0.0.0:3333/ontology/0001/freetest/v2".toSmartIri.toOntologySchema(InternalSchema) + + "The ontology helper" should { + + "determine the least strict cardinality allowed for a (inherited) property from a list of classes" in { + + val cacheDataFuture: Future[OntologyCacheData] = Cache.getCacheData + val cacheData: OntologyCacheData = Await.result(cacheDataFuture, 2.seconds) + + // define the classes + val mayHaveMany = freetestOntologyIri.makeEntityIri("PubMayHaveMany").toOntologySchema(InternalSchema) // 0-n + val mustHaveSome = freetestOntologyIri.makeEntityIri("PubMustHaveSome").toOntologySchema(InternalSchema) // 1-n + val mayHaveOne = freetestOntologyIri.makeEntityIri("PubMayHaveOne").toOntologySchema(InternalSchema) // 0-1 + val mustHaveOne = freetestOntologyIri.makeEntityIri("PubMustHaveOne").toOntologySchema(InternalSchema) // 1 + + val hasPublicationDateProperty = freetestOntologyIri.makeEntityIri("hasPublicationDate") + + // define all test cases and the expected results + val testCases: List[(Set[SmartIri], Option[Cardinality])] = List( + (Set(mayHaveMany), Some(MayHaveMany)), + (Set(mustHaveSome), Some(MustHaveSome)), + (Set(mayHaveOne), Some(MayHaveOne)), + (Set(mustHaveOne), Some(MustHaveOne)), + (Set(mayHaveMany, mustHaveSome), Some(MustHaveSome)), + (Set(mayHaveMany, mayHaveOne), Some(MayHaveOne)), + (Set(mayHaveMany, mustHaveOne), Some(MustHaveOne)), + (Set(mustHaveSome, mayHaveOne), Some(MustHaveOne)), + (Set(mustHaveSome, mustHaveOne), Some(MustHaveOne)), + (Set(mayHaveOne, mustHaveOne), Some(MustHaveOne)), + (Set(mayHaveMany, mustHaveSome, mayHaveOne), Some(MustHaveOne)), + (Set(mayHaveMany, mustHaveSome, mustHaveOne), Some(MustHaveOne)), + (Set(mayHaveMany, mayHaveOne, mustHaveOne), Some(MustHaveOne)), + (Set(mustHaveSome, mayHaveOne, mustHaveOne), Some(MustHaveOne)), + (Set(mayHaveMany, mustHaveSome, mayHaveOne, mustHaveOne), Some(MustHaveOne)) + ) + + def getStrictest(classes: Set[SmartIri]): Option[Cardinality] = + OntologyHelpers + .getStrictestCardinalitiesFromClasses(classes, cacheData) + .get(hasPublicationDateProperty) + .map(card => card.cardinality) + + testCases.map { case (testCase: Set[SmartIri], expectedResult: Option[Cardinality]) => + assert(getStrictest(testCase) == expectedResult) + } + + } + } +} diff --git a/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheInMemImplZSpec.scala b/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheInMemImplZSpec.scala index 594771b02a..a94e5ad312 100644 --- a/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheInMemImplZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheInMemImplZSpec.scala @@ -25,8 +25,8 @@ object CacheInMemImplZSpec extends ZIOSpecDefault { StringFormatter.initForTest() implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance - private val user: UserADM = SharedTestDataADM.imagesUser01 - private val userWithApostrophe = UserADM( + val user: UserADM = SharedTestDataADM.imagesUser01 + val userWithApostrophe = UserADM( id = "http://rdfh.ch/users/aaaaaab71e7b0e01", username = "user_with_apostrophe", email = "userWithApostrophe@example.org", @@ -36,7 +36,7 @@ object CacheInMemImplZSpec extends ZIOSpecDefault { lang = "en" ) - private val project: ProjectADM = SharedTestDataADM.imagesProject + val project: ProjectADM = SharedTestDataADM.imagesProject /** * Defines a layer which encompases all dependencies that are needed for diff --git a/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheRedisImplZSpec.scala b/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheRedisImplZSpec.scala index 95ab752a2b..d2fd0ab2f0 100644 --- a/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheRedisImplZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/store/cache/impl/CacheRedisImplZSpec.scala @@ -26,8 +26,8 @@ object CacheRedisImplZSpec extends ZIOSpecDefault { StringFormatter.initForTest() implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance - private val user: UserADM = SharedTestDataADM.imagesUser01 - private val project: ProjectADM = SharedTestDataADM.imagesProject + val user: UserADM = SharedTestDataADM.imagesUser01 + val project: ProjectADM = SharedTestDataADM.imagesProject /** * Defines a layer which encompases all dependencies that are needed for diff --git a/webapi/src/test/scala/org/knora/webapi/store/cache/serialization/CacheSerializationZSpec.scala b/webapi/src/test/scala/org/knora/webapi/store/cache/serialization/CacheSerializationZSpec.scala index 8f1a27daa3..b8174afbce 100644 --- a/webapi/src/test/scala/org/knora/webapi/store/cache/serialization/CacheSerializationZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/store/cache/serialization/CacheSerializationZSpec.scala @@ -18,8 +18,8 @@ import org.knora.webapi.store.cache.serialization.CacheSerialization */ object CacheSerializationZSpec extends ZIOSpecDefault { - private val user = SharedTestDataADM.imagesUser01 - private val project = SharedTestDataADM.imagesProject + val user = SharedTestDataADM.imagesUser01 + val project = SharedTestDataADM.imagesProject def spec = suite("CacheSerializationSpec")( test("successfully serialize and deserialize a user") { diff --git a/webapi/src/test/scala/org/knora/webapi/util/Base64UrlCheckDigitZSpec.scala b/webapi/src/test/scala/org/knora/webapi/util/Base64UrlCheckDigitZSpec.scala index 86d5907505..07bbf933b7 100644 --- a/webapi/src/test/scala/org/knora/webapi/util/Base64UrlCheckDigitZSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/util/Base64UrlCheckDigitZSpec.scala @@ -15,9 +15,9 @@ import zio.test.TestEnvironment * Tests [[Base64UrlCheckDigit]]. */ object Base64UrlCheckDigitZSpec extends ZIOSpecDefault { - private val base64UrlCheckDigit = new Base64UrlCheckDigit - private val correctResourceID = "cmfk1DMHRBiR4-_6HXpEFA" - private val correctResourceIDCheckDigit = "n" + val base64UrlCheckDigit = new Base64UrlCheckDigit + val correctResourceID = "cmfk1DMHRBiR4-_6HXpEFA" + val correctResourceIDCheckDigit = "n" def spec = suite("Base64UrlCheckDigitZSpec")( test("reject a string without a check digit") {