From 02f828c5b5248c0860e44a937c96cad58bff4f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 19:48:54 +0100 Subject: [PATCH] refactor: Make Project.description typed --- .../IntegrationTestAdminJsonProtocol.scala | 9 ++++++ .../webapi/sharedtestdata/ProjectInfo.scala | 2 +- .../sharedtestdata/SharedTestDataADM.scala | 30 +++++++++++-------- .../webapi/slice/admin/api/Examples.scala | 3 +- .../admin/api/model/ProjectsMessagesADM.scala | 3 +- .../admin/domain/service/ProjectService.scala | 6 ++-- .../domain/service/ProjectServiceSpec.scala | 2 +- 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala index da2ff2d18a..b98d07e61e 100644 --- a/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala +++ b/integration/src/test/scala/org/knora/webapi/messages/admin/responder/IntegrationTestAdminJsonProtocol.scala @@ -39,6 +39,7 @@ import org.knora.webapi.messages.admin.responder.usersmessages.UserProjectAdminM import org.knora.webapi.messages.admin.responder.usersmessages.UserProjectMembershipsGetResponseADM import org.knora.webapi.messages.admin.responder.usersmessages.UserResponseADM import org.knora.webapi.messages.admin.responder.usersmessages.UsersGetResponseADM +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtocol import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.api.model.ProjectAdminMembersGetResponseADM @@ -46,6 +47,7 @@ import org.knora.webapi.slice.admin.api.model.ProjectMembersGetResponseADM import org.knora.webapi.slice.admin.api.model.ProjectOperationResponseADM import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Description import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo @@ -206,6 +208,13 @@ object IntegrationTestAdminJsonProtocol extends TriplestoreJsonProtocol { ), ) + implicit object DescriptionFormat extends JsonFormat[Description] with TriplestoreJsonProtocol { + val lit = implicitly[JsonFormat[StringLiteralV2]] + override def write(obj: Description): JsValue = lit.write(obj.value) + override def read(json: JsValue): Description = Description + .from(lit.read(json)) + .fold(err => throw DeserializationException(err), identity) + } trait StringValueFormat[T <: StringValue] extends JsonFormat[T] { self => def from: String => Either[String, T] override def write(v: T): JsValue = JsString(v.value) diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala index 466f842d84..bc3b5ba924 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/ProjectInfo.scala @@ -41,7 +41,7 @@ object ProjectInfo { shortname = project.shortname.value, shortcode = project.shortcode.value, longname = project.longname.map(_.value), - description = project.description.headOption.map(_.value), + description = project.description.map(_.value).headOption.map(_.value), keywords = project.keywords.headOption.map(_ => project.keywords.mkString(", ")), logo = project.logo.map(_.value), ontologies = project.ontologies, diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index aef55eb351..ef5cee5ee3 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -16,6 +16,7 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.slice.admin.api.model.Project import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Description import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.Logo import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname @@ -166,7 +167,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("SystemProject"), shortcode = Shortcode.unsafeFrom("FFFF"), longname = Some(Longname.unsafeFrom("Knora System Project")), - description = Seq(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))), + description = + List(StringLiteralV2.from(value = "Knora System Project", language = Some("en"))).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq( @@ -187,7 +189,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("DefaultSharedOntologiesProject"), shortcode = Shortcode.unsafeFrom("0000"), longname = Some(Longname.unsafeFrom("Default Knora Shared Ontologies Project")), - description = Seq(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))), + description = List(StringLiteralV2.from(value = "Default Knora Shared Ontologies Project", language = Some("en"))) + .map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq.empty[IRI], @@ -301,7 +304,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("images"), shortcode = Shortcode.unsafeFrom("00FF"), longname = Some(Longname.unsafeFrom("Image Collection Demo")), - description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), + description = List(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))) + .map(Description.unsafeFrom), keywords = List("images", "collection").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI), @@ -317,7 +321,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("images"), shortcode = Shortcode.unsafeFrom("00FF"), longname = Some(Longname.unsafeFrom("Image Collection Demo")), - description = Seq(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))), + description = List(StringLiteralV2.from(value = "A demo project of a collection of images", language = Some("en"))) + .map(Description.unsafeFrom), keywords = List("images", "collection").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.IMAGES_ONTOLOGY_IRI_LocalHost), @@ -461,13 +466,13 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("incunabula"), shortcode = Shortcode.unsafeFrom("0803"), longname = Some(Longname.unsafeFrom("Bilderfolgen Basler Frühdrucke")), - description = Seq( + description = List( StringLiteralV2.from( value = "

Das interdisziplinäre Forschungsprojekt \"Die Bilderfolgen der Basler Frühdrucke: Spätmittelalterliche Didaxe als Bild-Text-Lektüre\" verbindet eine umfassende kunstwissenschaftliche Analyse der Bezüge zwischen den Bildern und Texten in den illustrierten Basler Inkunabeln mit der Digitalisierung der Bestände der Universitätsbibliothek und der Entwicklung einer elektronischen Edition in der Form einer neuartigen Web-0.2-Applikation.\n

\n

Das Projekt wird durchgeführt vom Kunsthistorischen Seminar der Universität Basel (Prof. B. Schellewald) und dem Digital Humanities Lab der Universität Basel (PD Dr. L. Rosenthaler).\n

\n

\nDas Kernstück der digitalen Edition besteht aus rund zwanzig reich bebilderten Frühdrucken aus vier verschiedenen Basler Offizinen. Viele davon sind bereits vor 1500 in mehreren Ausgaben erschienen, einige fast gleichzeitig auf Deutsch und Lateinisch. Es handelt sich um eine ausserordentlich vielfältige Produktion; neben dem Heilsspiegel finden sich ein Roman, die Melusine, die Reisebeschreibungen des Jean de Mandeville, einige Gebets- und Erbauungsbüchlein, theologische Schriften, Fastenpredigten, die Leben der Heiligen Fridolin und Meinrad, das berühmte Narrenschiff sowie die Exempelsammlung des Ritters vom Thurn.\n

\nDie Internetpublikation macht das digitalisierte Korpus dieser Frühdrucke durch die Möglichkeiten nichtlinearer Verknüpfung und Kommentierung der Bilder und Texte, für die wissenschaftliche Edition sowie für die Erforschung der Bilder und Texte nutzbar machen. Auch können bereits bestehende und entstehende Online-Editionen damit verknüpft werden , wodurch die Nutzung von Datenbanken anderer Institutionen im Hinblick auf unser Corpus optimiert wird.\n

", language = None, ), - ), + ).map(Description.unsafeFrom), keywords = List( "Basler Frühdrucke", "Inkunabel", @@ -498,13 +503,13 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("incunabula"), shortcode = Shortcode.unsafeFrom("0803"), longname = Some(Longname.unsafeFrom("Bilderfolgen Basler Frühdrucke")), - description = Seq( + description = List( StringLiteralV2.from( value = "

Das interdisziplinäre Forschungsprojekt \"Die Bilderfolgen der Basler Frühdrucke: Spätmittelalterliche Didaxe als Bild-Text-Lektüre\" verbindet eine umfassende kunstwissenschaftliche Analyse der Bezüge zwischen den Bildern und Texten in den illustrierten Basler Inkunabeln mit der Digitalisierung der Bestände der Universitätsbibliothek und der Entwicklung einer elektronischen Edition in der Form einer neuartigen Web-0.2-Applikation.\n

\n

Das Projekt wird durchgeführt vom Kunsthistorischen Seminar der Universität Basel (Prof. B. Schellewald) und dem Digital Humanities Lab der Universität Basel (PD Dr. L. Rosenthaler).\n

\n

\nDas Kernstück der digitalen Edition besteht aus rund zwanzig reich bebilderten Frühdrucken aus vier verschiedenen Basler Offizinen. Viele davon sind bereits vor 1500 in mehreren Ausgaben erschienen, einige fast gleichzeitig auf Deutsch und Lateinisch. Es handelt sich um eine ausserordentlich vielfältige Produktion; neben dem Heilsspiegel finden sich ein Roman, die Melusine, die Reisebeschreibungen des Jean de Mandeville, einige Gebets- und Erbauungsbüchlein, theologische Schriften, Fastenpredigten, die Leben der Heiligen Fridolin und Meinrad, das berühmte Narrenschiff sowie die Exempelsammlung des Ritters vom Thurn.\n

\nDie Internetpublikation macht das digitalisierte Korpus dieser Frühdrucke durch die Möglichkeiten nichtlinearer Verknüpfung und Kommentierung der Bilder und Texte, für die wissenschaftliche Edition sowie für die Erforschung der Bilder und Texte nutzbar machen. Auch können bereits bestehende und entstehende Online-Editionen damit verknüpft werden , wodurch die Nutzung von Datenbanken anderer Institutionen im Hinblick auf unser Corpus optimiert wird.\n

", language = None, ), - ), + ).map(Description.unsafeFrom), keywords = List( "Basler Frühdrucke", "Inkunabel", @@ -633,7 +638,7 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("anything"), shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Anything Project")), - description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), + description = List(StringLiteralV2.from(value = "Anything Project", language = None)).map(Description.unsafeFrom), keywords = List("things", "arbitrary test data").map(Keyword.unsafeFrom), logo = None, ontologies = Seq(SharedOntologyTestDataADM.ANYTHING_ONTOLOGY_IRI, SharedOntologyTestDataADM.SomethingOntologyIri), @@ -648,7 +653,7 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("anything"), shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Anything Project")), - description = Seq(StringLiteralV2.from(value = "Anything Project", language = None)), + description = List(StringLiteralV2.from(value = "Anything Project", language = None)).map(Description.unsafeFrom), keywords = List("things", "arbitrary test data").map(Keyword.unsafeFrom), logo = None, ontologies = Seq( @@ -685,7 +690,8 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("beol"), shortcode = Shortcode.unsafeFrom("0801"), longname = Some(Longname.unsafeFrom("Bernoulli-Euler Online")), - description = Seq(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)), + description = + List(StringLiteralV2.from(value = "Bernoulli-Euler Online", language = None)).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq( @@ -741,7 +747,7 @@ object SharedTestDataADM { shortname = Shortname.unsafeFrom("dokubib"), shortcode = Shortcode.unsafeFrom("0804"), longname = Some(Longname.unsafeFrom("Dokubib")), - description = Seq(StringLiteralV2.from(value = "Dokubib", language = None)), + description = List(StringLiteralV2.from(value = "Dokubib", language = None)).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = Seq("http://www.knora.org/ontology/0804/dokubib"), diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala index 0abc38efac..fc0135555e 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/Examples.scala @@ -24,6 +24,7 @@ import org.knora.webapi.slice.admin.domain.model.GroupName import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraProject.CopyrightAttribution +import org.knora.webapi.slice.admin.domain.model.KnoraProject.Description import org.knora.webapi.slice.admin.domain.model.KnoraProject.Keyword import org.knora.webapi.slice.admin.domain.model.KnoraProject.License import org.knora.webapi.slice.admin.domain.model.KnoraProject.Longname @@ -95,7 +96,7 @@ object Examples { shortname = Shortname.unsafeFrom("example"), shortcode = Shortcode.unsafeFrom("0001"), longname = Some(Longname.unsafeFrom("Example Project")), - description = Seq(StringLiteralV2.from("An example project", Some("en"))), + description = List(StringLiteralV2.from("An example project", Some("en"))).map(Description.unsafeFrom), keywords = List("example", "project").map(Keyword.unsafeFrom), logo = None, status = Active, diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala index ba5dc64f96..f7f3d60535 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/model/ProjectsMessagesADM.scala @@ -10,7 +10,6 @@ import zio.json.JsonCodec import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM -import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.slice.admin.api.Codecs.ZioJsonCodec.* import org.knora.webapi.slice.admin.domain.model.KnoraProject.* import org.knora.webapi.slice.admin.domain.model.RestrictedView @@ -35,7 +34,7 @@ case class Project( shortname: Shortname, shortcode: Shortcode, longname: Option[Longname], - description: Seq[StringLiteralV2], + description: List[Description], keywords: List[Keyword], logo: Option[Logo], ontologies: Seq[IRI], diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala index 84922ee815..142b0b73eb 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/ProjectService.scala @@ -50,7 +50,7 @@ final case class ProjectService( knoraProject.shortname, knoraProject.shortcode, knoraProject.longname, - knoraProject.description.map(_.value), + knoraProject.description.toList, knoraProject.keywords, knoraProject.logo, ontologies, @@ -67,9 +67,7 @@ final case class ProjectService( shortname = project.shortname, shortcode = project.shortcode, longname = project.longname, - description = NonEmptyChunk - .fromIterable(project.description.head, project.description.tail) - .map(Description.unsafeFrom), + description = NonEmptyChunk.fromIterable(project.description.head, project.description.tail), keywords = project.keywords, logo = project.logo, status = project.status, diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala index f7badf15e1..325f7e58a4 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/service/ProjectServiceSpec.scala @@ -29,7 +29,7 @@ object ProjectServiceSpec extends ZIOSpecDefault { shortname = shortname, shortcode = shortcode, longname = None, - description = List(StringLiteralV2.from("description not used in test", None)), + description = List(StringLiteralV2.from("description not used in test", None)).map(Description.unsafeFrom), keywords = List.empty, logo = None, ontologies = List.empty,