From 8d08abd7a084a81e84f09a69141d9043a650411f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Thu, 4 May 2023 15:17:59 +0200 Subject: [PATCH] refactor: Improve KnoraProject model NO-TICKET (#2648) --- .../admin/domain/model/KnoraProject.scala | 4 ++- .../repo/service/KnoraProjectRepoLive.scala | 4 +-- .../repo/service/PredicateObjectMapper.scala | 27 +++++++++++++++++-- .../service/ProjectADMServiceSpec.scala | 4 ++- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala index 96940fe524..7daa93f2c4 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraProject.scala @@ -4,6 +4,8 @@ */ package org.knora.webapi.slice.admin.domain.model +import zio.NonEmptyChunk + import dsp.valueobjects.V2.StringLiteralV2 import org.knora.webapi.slice.resourceinfo.domain.InternalIri @@ -12,7 +14,7 @@ case class KnoraProject( shortname: String, shortcode: String, longname: Option[String], - description: List[StringLiteralV2], + description: NonEmptyChunk[StringLiteralV2], keywords: List[String], logo: Option[String], status: Boolean, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala index 8e3d88d517..47354aa657 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraProjectRepoLive.scala @@ -67,8 +67,8 @@ final case class KnoraProjectRepoLive( shortcode <- mapper.getSingleOrFail[StringLiteralV2](ProjectShortcode, propsMap).map(_.value) longname <- mapper.getSingleOption[StringLiteralV2](ProjectLongname, propsMap).map(_.map(_.value)) description <- mapper - .getListOrFail[StringLiteralV2](ProjectDescription, propsMap) - .map(_.map(desc => V2.StringLiteralV2(desc.value, desc.language))) + .getNonEmptyChunkOrFail[StringLiteralV2](ProjectDescription, propsMap) + .map(_.map(it => V2.StringLiteralV2(it.value, it.language))) keywords <- mapper.getList[StringLiteralV2](ProjectKeyword, propsMap).map(_.map(_.value).sorted) logo <- mapper.getSingleOption[StringLiteralV2](ProjectLogo, propsMap).map(_.map(_.value)) status <- mapper.getSingleOrFail[BooleanLiteralV2](Status, propsMap).map(_.value) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/common/repo/service/PredicateObjectMapper.scala b/webapi/src/main/scala/org/knora/webapi/slice/common/repo/service/PredicateObjectMapper.scala index 36371a626e..4751589493 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/common/repo/service/PredicateObjectMapper.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/common/repo/service/PredicateObjectMapper.scala @@ -61,9 +61,32 @@ final case class PredicateObjectMapper(private val iriConverter: IriConverter) { * @return a list of values, fails with an [[InconsistentRepositoryDataException]] if key was not present. */ def getListOrFail[A <: LiteralV2](key: IRI, propertiesMap: ConstructPredicateObjects): Task[List[A]] = - getListOption[A](key, propertiesMap) - .flatMap(ZIO.fromOption(_)) + getListOption[A](key, propertiesMap).some + .orElseFail(InconsistentRepositoryDataException(s"PropertiesMap has no $key defined.")) + + /** + * Returns a [[NonEmptyChunk]] of values for the given key. + * Fails during runtime if the value could not be cast to the given type. + * + * @param key the key to look for. + * @param propertiesMap the map to look in. + * @tparam A the type of the values. + * @return A [[NonEmptyChunk]] of values, + * Fails with an [[InconsistentRepositoryDataException]] if key was not present. + * Fails with an [[InconsistentRepositoryDataException]] if the list of values was empty. + */ + def getNonEmptyChunkOrFail[A <: LiteralV2]( + key: IRI, + propertiesMap: ConstructPredicateObjects + ): Task[NonEmptyChunk[A]] = + getListOption[A](key, propertiesMap).some .orElseFail(InconsistentRepositoryDataException(s"PropertiesMap has no $key defined.")) + .flatMap(list => + ZIO + .fail(InconsistentRepositoryDataException(s"PropertiesMap has $key defined but list of values is empty.")) + .when(list.isEmpty) + .as(NonEmptyChunk.fromIterable(list.head, list.tail)) + ) /** * Returns an optional single value for the given key. diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMServiceSpec.scala index 949a30e358..0a7273f505 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectADMServiceSpec.scala @@ -5,6 +5,7 @@ package org.knora.webapi.slice.admin.domain.service +import zio.NonEmptyChunk import zio.test.Spec import zio.test.ZIOSpecDefault import zio.test.assertTrue @@ -46,7 +47,8 @@ object ProjectADMServiceSpec extends ZIOSpecDefault { shortname = shortname, shortcode = shortcode, longname = None, - description = List(StringLiteralV2("description not used in test but is required by constructor", None)), + description = + NonEmptyChunk(StringLiteralV2("description not used in test but is required by constructor", None)), keywords = List.empty, logo = None, status = true,