From 8d5741d7b7ed4952d5839f40b4aa3439fee038c2 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 7 Oct 2021 14:54:27 +0200 Subject: [PATCH 01/32] refactor: fix filename --- .../{GroupsPayloadsADM.scala => GroupPayloadsADM.scala} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/{GroupsPayloadsADM.scala => GroupPayloadsADM.scala} (100%) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupPayloadsADM.scala similarity index 100% rename from webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsPayloadsADM.scala rename to webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupPayloadsADM.scala From cd2aef596308f658d5693482b09ac585dd87c339 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 8 Oct 2021 11:27:05 +0200 Subject: [PATCH 02/32] feat: add create list payload & value objects --- .../listsmessages/ListPayloadsADM.scala | 34 ++++++++++++++++ .../valueObjects/ValueObjectsADM.scala | 40 +++++++++++++++---- 2 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala new file mode 100644 index 0000000000..ded4b14fe6 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -0,0 +1,34 @@ +package org.knora.webapi.messages.admin.responder.listsmessages + +import org.knora.webapi.IRI +import org.knora.webapi.messages.admin.responder.valueObjects.{Name, Labels, Comments} + +/** + * List payload + */ +sealed abstract case class ListCreatePayloadADM private ( + id: Option[IRI] = None, + projectIri: IRI, + name: Option[Name] = None, + labels: Labels, + comments: Comments +) + +object ListCreatePayloadADM { + + /** The create constructor */ + def create( + id: Option[IRI], + projectIri: IRI, + name: Option[Name], + labels: Labels, + comments: Comments + ): ListCreatePayloadADM = + new ListCreatePayloadADM( + id = id, + projectIri = projectIri, + name = name, + labels = labels, + comments = comments + ) {} +} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala index 93c3d1c663..3c40e7560b 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala @@ -200,18 +200,31 @@ object Logo { } } -/** Groups value objects */ +/** Lists value objects */ /** - * Group Name value object. + * Labels value object. */ -sealed abstract case class Name private (value: String) -object Name { - def create(value: String): Either[Throwable, Name] = +sealed abstract case class Labels private (value: Seq[StringLiteralV2]) +object Labels { + def create(value: Seq[StringLiteralV2]): Either[Throwable, Labels] = if (value.isEmpty) { - Left(BadRequestException("Missing Name")) + Left(BadRequestException("Missing labels")) } else { - Right(new Name(value) {}) + Right(new Labels(value) {}) + } +} + +/** + * Comments value object. + */ +sealed abstract case class Comments private (value: Seq[StringLiteralV2]) +object Comments { + def create(value: Seq[StringLiteralV2]): Either[Throwable, Comments] = + if (value.isEmpty) { + Left(BadRequestException("Missing comments")) + } else { + Right(new Comments(value) {}) } } @@ -247,3 +260,16 @@ object Description { Right(new Description(value) {}) } } + +/** + * Name value object. + */ +sealed abstract case class Name private (value: String) +object Name { + def create(value: String): Either[Throwable, Name] = + if (value.isEmpty) { + Left(BadRequestException("Missing Name")) + } else { + Right(new Name(value) {}) + } +} From 9d7e32b9332506522664d7f378ce7d19cb1111d6 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 13 Oct 2021 10:21:22 +0200 Subject: [PATCH 03/32] feat: add update list payload & value objects + update routes & responder --- .../listsmessages/ListPayloadsADM.scala | 68 +++++++++++++++---- .../listsmessages/ListsMessagesADM.scala | 6 +- .../valueObjects/ValueObjectsADM.scala | 13 ++++ .../responders/admin/ListsResponderADM.scala | 29 ++++---- .../webapi/routing/admin/GroupsRouteADM.scala | 4 +- .../admin/lists/NewListsRouteADMFeature.scala | 44 +++++++++++- .../admin/lists/OldListsRouteADMFeature.scala | 63 +++++++++++++++-- 7 files changed, 188 insertions(+), 39 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index ded4b14fe6..31f4b6be75 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -1,34 +1,74 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI -import org.knora.webapi.messages.admin.responder.valueObjects.{Name, Labels, Comments} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 + +///** +// * List payload +// */ +//sealed abstract case class ListCreatePayloadADM private ( +// id: Option[IRI] = None, +// projectIri: IRI, +// name: Option[Name] = None, +// labels: Labels, +// comments: Comments +//) +// +//object ListCreatePayloadADM { +// def create( +// id: Option[IRI], +// projectIri: IRI, +// name: Option[Name], +// labels: Labels, +// comments: Comments +// ): ListCreatePayloadADM = new ListCreatePayloadADM(id, projectIri, name, labels, comments) {} +//} /** - * List payload + * Node creation payload */ -sealed abstract case class ListCreatePayloadADM private ( +sealed abstract case class NodeCreatePayloadADM private ( id: Option[IRI] = None, + parentNodeIri: Option[IRI] = None, projectIri: IRI, name: Option[Name] = None, + position: Option[Position] = None, labels: Labels, comments: Comments ) -object ListCreatePayloadADM { - - /** The create constructor */ +object NodeCreatePayloadADM { def create( id: Option[IRI], + parentNodeIri: Option[IRI], projectIri: IRI, name: Option[Name], + position: Option[Position], labels: Labels, comments: Comments - ): ListCreatePayloadADM = - new ListCreatePayloadADM( - id = id, - projectIri = projectIri, - name = name, - labels = labels, - comments = comments - ) {} + ): NodeCreatePayloadADM = new NodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, labels, comments) {} +} + +sealed abstract case class NodeChangePayloadADM private ( + listIri: IRI, + projectIri: IRI, + hasRootNode: Option[IRI] = None, + position: Option[Position] = None, + name: Option[Name] = None, + labels: Option[Labels] = None, + comments: Option[Comments] = None +) + +object NodeChangePayloadADM { + def create( + listIri: IRI, + projectIri: IRI, + hasRootNode: Option[IRI], + position: Option[Position], + name: Option[Name], + labels: Option[Labels], + comments: Option[Comments] + ): NodeChangePayloadADM = + new NodeChangePayloadADM(listIri, projectIri, hasRootNode, position, name, labels, comments) {} } diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index d40b0a89d6..1f32435a4f 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -316,13 +316,13 @@ case class NodePathGetRequestADM(iri: IRI, featureFactoryConfig: FeatureFactoryC /** * Requests the creation of a new list. * - * @param createRootNode the [[CreateNodeApiRequestADM]] information used for creating the root node of the list. + * @param createRootNode the [[NodeCreatePayloadADM]] information used for creating the root node of the list. * @param featureFactoryConfig the feature factory configuration. * @param requestingUser the user creating the new list. * @param apiRequestID the ID of the API request. */ case class ListCreateRequestADM( - createRootNode: CreateNodeApiRequestADM, + createRootNode: NodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -373,7 +373,7 @@ case class NodeInfoChangeRequestADM( * @param apiRequestID the ID of the API request. */ case class ListChildNodeCreateRequestADM( - createChildNodeRequest: CreateNodeApiRequestADM, + createChildNodeRequest: NodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala index 3c40e7560b..fa15d3893d 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala @@ -228,6 +228,19 @@ object Comments { } } +/** + * Position value object. + */ +sealed abstract case class Position private (value: Int) +object Position { + def create(value: Int): Either[Throwable, Position] = + if (value <= 0) { // TODO: what should be the criteria + Left(BadRequestException("Missing shouldn't be <= 0")) + } else { + Right(new Position(value) {}) + } +} + /** Shared value objects */ /** diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 748716ecd6..d43b0a9cbe 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -20,7 +20,6 @@ package org.knora.webapi.responders.admin import java.util.UUID - import akka.http.scaladsl.util.FastFuture import akka.pattern._ import org.knora.webapi._ @@ -31,6 +30,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtil import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectGetADM, ProjectIdentifierADM} import org.knora.webapi.messages.admin.responder.usersmessages._ +import org.knora.webapi.messages.admin.responder.valueObjects.Name import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.util.{KnoraSystemInstances, ResponderData} @@ -847,12 +847,12 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @return a [newListNodeIri] */ private def createNode( - createNodeRequest: CreateNodeApiRequestADM, + createNodeRequest: NodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig ): Future[IRI] = { def getPositionOfNewChild(children: Seq[ListChildNodeADM]): Int = { - if (createNodeRequest.position.exists(_ > children.size)) { + if (createNodeRequest.position.get.value > children.size) { val givenPosition = createNodeRequest.position.get throw BadRequestException( s"Invalid position given $givenPosition, maximum allowed position is = ${children.size}." @@ -862,7 +862,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde val position = if (createNodeRequest.position.isEmpty || createNodeRequest.position.exists(_.equals(-1))) { children.size } else { - createNodeRequest.position.get + createNodeRequest.position.get.value } position } @@ -935,9 +935,12 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } /* verify that the list node name is unique for the project */ - projectUniqueNodeName <- listNodeNameIsProjectUnique(createNodeRequest.projectIri, createNodeRequest.name) + projectUniqueNodeName <- listNodeNameIsProjectUnique( + createNodeRequest.projectIri, + Some(createNodeRequest.name.get.value) //TODO: dirty solution? + ) _ = if (!projectUniqueNodeName) { - val escapedName = createNodeRequest.name.get + val escapedName = createNodeRequest.name.get.value val unescapedName = stringFormatter.fromSparqlEncodedString(escapedName) throw BadRequestException( s"The node name ${unescapedName} is already used by a list inside the project ${createNodeRequest.projectIri}." @@ -975,9 +978,9 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde parentNodeIri = createNodeRequest.parentNodeIri, rootNodeIri = rootNodeIri, position = position, - maybeName = createNodeRequest.name, - maybeLabels = createNodeRequest.labels, - maybeComments = createNodeRequest.comments + maybeName = Some(createNodeRequest.name.get.value), //TODO: instead of this should be SPARQL updated? + maybeLabels = createNodeRequest.labels.value, + maybeComments = createNodeRequest.comments.value ) .toString @@ -994,7 +997,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @return a [[RootNodeInfoGetResponseADM]] */ private def listCreateRequestADM( - createRootRequest: CreateNodeApiRequestADM, + createRootRequest: NodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[ListGetResponseADM] = { @@ -1003,7 +1006,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * The actual task run with an IRI lock. */ def listCreateTask( - createRootRequest: CreateNodeApiRequestADM, + createRootRequest: NodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[ListGetResponseADM] = @@ -1135,7 +1138,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @return a [[ChildNodeInfoGetResponseADM]] */ private def listChildNodeCreateRequestADM( - createChildNodeRequest: CreateNodeApiRequestADM, + createChildNodeRequest: NodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[ChildNodeInfoGetResponseADM] = { @@ -1144,7 +1147,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * The actual task run with an IRI lock. */ def listChildNodeCreateTask( - createChildNodeRequest: CreateNodeApiRequestADM, + createChildNodeRequest: NodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[ChildNodeInfoGetResponseADM] = diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala index 038a117211..a133abda51 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala @@ -94,7 +94,7 @@ class GroupsRouteADM(routeData: KnoraRouteData) entity(as[CreateGroupApiRequestADM]) { apiRequest => requestContext => val groupCreatePayloadADM: GroupCreatePayloadADM = GroupCreatePayloadADM.create( id = stringFormatter - .validateAndEscapeOptionalIri(apiRequest.id, throw BadRequestException(s"Invalid group IRI")), + .validateAndEscapeOptionalIri(apiRequest.id, throw BadRequestException(s"Invalid custom group IRI")), name = Name.create(apiRequest.name).fold(e => throw e, v => v), descriptions = Description.create(apiRequest.descriptions).fold(e => throw e, v => v), project = stringFormatter @@ -136,7 +136,7 @@ class GroupsRouteADM(routeData: KnoraRouteData) /* returns a single group identified through iri */ requestContext => val checkedGroupIri = - stringFormatter.validateAndEscapeIri(value, throw BadRequestException(s"Invalid group IRI $value")) + stringFormatter.validateAndEscapeIri(value, throw BadRequestException(s"Invalid custom group IRI $value")) val requestMessage = for { requestingUser <- getUserADM( diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 086b4ef97b..6f71a8c2fa 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -20,15 +20,16 @@ package org.knora.webapi.routing.admin.lists import java.util.UUID - import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{PathMatcher, Route} import io.swagger.annotations._ + import javax.ws.rs.Path import org.knora.webapi.IRI import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} import org.knora.webapi.messages.admin.responder.listsmessages._ +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -155,6 +156,43 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list item (root or child node) */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => + val maybeName: Option[Name] = apiRequest.name match { + case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + case None => None + } + +// val listCreatePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM.create( +// id = stringFormatter +// .validateAndEscapeOptionalIri(apiRequest.id, throw BadRequestException(s"Invalid custom list IRI")), +// projectIri = stringFormatter +// .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), +// name = maybeName, +// labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), +// comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) +// ) + + val maybePosition: Option[Position] = apiRequest.position match { + case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + case None => None + } + + val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM.create( + id = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.id, + throw BadRequestException(s"Invalid custom node IRI") + ), + parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.parentNodeIri, + throw BadRequestException(s"Invalid parent node IRI") + ), + projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + name = maybeName, + position = maybePosition, + labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), + comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) + ) + val requestMessage = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) // Is parent node IRI given in the payload? @@ -162,7 +200,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) if (apiRequest.parentNodeIri.isEmpty) { // No, create a new list with given information of its root node. ListCreateRequestADM( - createRootNode = apiRequest.escape, + createRootNode = nodeCreatePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -170,7 +208,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) } else { // Yes, create a new child and attach it to the parent node. ListChildNodeCreateRequestADM( - createChildNodeRequest = apiRequest.escape, + createChildNodeRequest = nodeCreatePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index a670d70953..7881b3ad71 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -20,15 +20,16 @@ package org.knora.webapi.routing.admin.lists import java.util.UUID - import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{PathMatcher, Route} import io.swagger.annotations._ + import javax.ws.rs.Path import org.knora.webapi.IRI import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} import org.knora.webapi.messages.admin.responder.listsmessages._ +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -129,13 +130,40 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => + val maybeName: Option[Name] = apiRequest.name match { + case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybePosition: Option[Position] = apiRequest.position match { + case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + case None => None + } + + val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM.create( + id = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.id, + throw BadRequestException(s"Invalid custom node IRI") + ), + parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.parentNodeIri, + throw BadRequestException(s"Invalid parent node IRI") + ), + projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + name = maybeName, + position = maybePosition, + labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), + comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) + ) + val requestMessage: Future[ListCreateRequestADM] = for { requestingUser <- getUserADM( requestContext = requestContext, featureFactoryConfig = featureFactoryConfig ) } yield ListCreateRequestADM( - createRootNode = apiRequest.escape, + createRootNode = nodeCreatePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -275,7 +303,34 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* add node to existing list node. the existing list node can be either the root or a child */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => - val _ = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) +// val _ = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) + + val maybeName: Option[Name] = apiRequest.name match { + case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybePosition: Option[Position] = apiRequest.position match { + case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + case None => None + } + + val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM.create( + id = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.id, + throw BadRequestException(s"Invalid custom node IRI") + ), + parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.parentNodeIri, + throw BadRequestException(s"Invalid parent node IRI") + ), + projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + name = maybeName, + position = maybePosition, + labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), + comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) + ) val requestMessage: Future[ListChildNodeCreateRequestADM] = for { requestingUser <- getUserADM( @@ -283,7 +338,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) featureFactoryConfig = featureFactoryConfig ) } yield ListChildNodeCreateRequestADM( - createChildNodeRequest = apiRequest.escape, + createChildNodeRequest = nodeCreatePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() From faf93a9ca14cb35e6ab8bb3ef13d493adbc2329d Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 13 Oct 2021 17:03:31 +0200 Subject: [PATCH 04/32] test: update test data --- .../listsmessages/ListPayloadsADM.scala | 9 +- .../listsmessages/ListsMessagesADM.scala | 2 +- .../valueObjects/ValueObjectsADM.scala | 5 +- .../responders/admin/ListsResponderADM.scala | 1 - .../sparql/admin/createNewListNode.scala.txt | 3 +- .../listsmessages/ListsMessagesADMSpec.scala | 57 ++++++--- .../admin/ListsResponderADMSpec.scala | 120 ++++++++++++------ 7 files changed, 125 insertions(+), 72 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index 31f4b6be75..535f9e5ca2 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -2,7 +2,6 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} -import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 ///** // * List payload @@ -40,11 +39,11 @@ sealed abstract case class NodeCreatePayloadADM private ( object NodeCreatePayloadADM { def create( - id: Option[IRI], - parentNodeIri: Option[IRI], + id: Option[IRI] = None, + parentNodeIri: Option[IRI] = None, projectIri: IRI, - name: Option[Name], - position: Option[Position], + name: Option[Name] = None, + position: Option[Position] = None, labels: Labels, comments: Comments ): NodeCreatePayloadADM = new NodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, labels, comments) {} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 1f32435a4f..bb562a2627 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -54,7 +54,7 @@ case class CreateListApiRequestADM( projectIri: IRI, name: Option[String] = None, labels: Seq[StringLiteralV2], - comments: Seq[StringLiteralV2] + comments: Seq[StringLiteralV2] // descriptions ) extends ListADMJsonProtocol { private val stringFormatter = StringFormatter.getInstanceForConstantOntologies diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala index fa15d3893d..2bccc6c466 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala @@ -4,6 +4,7 @@ import org.knora.webapi.LanguageCodes import org.knora.webapi.exceptions.{AssertionException, BadRequestException} import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 +import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.INVALID_POSITION import scala.util.matching.Regex @@ -234,8 +235,8 @@ object Comments { sealed abstract case class Position private (value: Int) object Position { def create(value: Int): Either[Throwable, Position] = - if (value <= 0) { // TODO: what should be the criteria - Left(BadRequestException("Missing shouldn't be <= 0")) + if (value < -1) { // TODO: what should be the criteria? + Left(BadRequestException(INVALID_POSITION)) } else { Right(new Position(value) {}) } diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index d43b0a9cbe..910c58c418 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -30,7 +30,6 @@ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtil import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectGetADM, ProjectIdentifierADM} import org.knora.webapi.messages.admin.responder.usersmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.Name import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.util.{KnoraSystemInstances, ResponderData} diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt index 51908c6b06..bd3a868dec 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt @@ -47,7 +47,7 @@ position: Option[Int], maybeName: Option[String], maybeLabels: Seq[StringLiteralV2], - maybeComments: Seq[StringLiteralV2] + maybeComments: Seq[StringLiteralV2] //this can be changed to maybeDescriptions ) PREFIX xsd: @@ -91,6 +91,7 @@ INSERT { @if(maybeComments.nonEmpty) { @for(comment <- maybeComments) { @if(comment.language.nonEmpty) { + // rdfs:comment can't be changed to descriptions because it breaks the data ?nodeIri rdfs:comment """@comment.value"""@@@{comment.language.get} . } else { ?nodeIri rdfs:comment """@comment.value"""^^xsd:string . diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index 3dae0cb0c2..badfc02f15 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -20,11 +20,11 @@ package org.knora.webapi.messages.admin.responder.listsmessages import java.util.UUID - import com.typesafe.config.ConfigFactory import org.knora.webapi.CoreSpec import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} import org.knora.webapi.sharedtestdata.SharedTestDataV1.IMAGES_PROJECT_IRI import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} @@ -146,11 +146,17 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'ForbiddenException' if user requesting `ListCreateApiRequestADM` is not system or project admin" in { val caught = intercept[ForbiddenException]( ListCreateRequestADM( - createRootNode = CreateNodeApiRequestADM( - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - labels = Seq(StringLiteralV2(value = "Neue Liste", language = Some("de"))), - comments = Seq.empty[StringLiteralV2] - ), + createRootNode = NodeCreatePayloadADM + .create( + projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, + labels = Labels + .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "Neuer Kommentar", language = Some("de")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser02, apiRequestID = UUID.randomUUID() @@ -210,7 +216,6 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw a 'BadRequestException' for `CreateListApiRequestADM` when an invalid list IRI is given" in { - // invalid list IRI val payload = s""" |{ @@ -360,12 +365,18 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'ForbiddenException' if user requesting `createChildNodeRequest` is not system or project admin" in { val caught = intercept[ForbiddenException]( ListChildNodeCreateRequestADM( - createChildNodeRequest = CreateNodeApiRequestADM( - parentNodeIri = Some(exampleListIri), - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - labels = Seq(StringLiteralV2(value = "New child node", language = Some("en"))), - comments = Seq.empty[StringLiteralV2] - ), + createChildNodeRequest = NodeCreatePayloadADM + .create( + parentNodeIri = Some(exampleListIri), + projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, + labels = Labels + .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser02, apiRequestID = UUID.randomUUID() @@ -377,13 +388,19 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'BadRequestException' if invalid position given in payload of `createChildNodeRequest`" in { val caught = intercept[BadRequestException]( ListChildNodeCreateRequestADM( - createChildNodeRequest = CreateNodeApiRequestADM( - parentNodeIri = Some(exampleListIri), - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - labels = Seq(StringLiteralV2(value = "New child node", language = Some("en"))), - position = Some(-3), - comments = Seq.empty[StringLiteralV2] - ), + createChildNodeRequest = NodeCreatePayloadADM + .create( + parentNodeIri = Some(exampleListIri), + projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, + position = Some(Position.create(-3).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 78f2b9c63b..33a1bad175 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -32,6 +32,7 @@ import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, Strin import org.knora.webapi.sharedtestdata.SharedTestDataV1._ import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} import org.knora.webapi.util.MutableTestIri +import org.knora.webapi.messages.admin.responder.valueObjects.{Name, Comments, Labels, Position} import scala.concurrent.duration._ @@ -176,12 +177,17 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "used to modify lists" should { "create a list" in { responderManager ! ListCreateRequestADM( - createRootNode = CreateNodeApiRequestADM( + createRootNode = NodeCreatePayloadADM.create( projectIri = IMAGES_PROJECT_IRI, - name = Some("neuelistename"), - labels = Seq(StringLiteralV2(value = "Neue Liste", language = Some("de"))), - comments = Seq.empty[StringLiteralV2] - ).escape, + name = Some(Name.create("neuelistename").fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "Neuer Kommentar", language = Some("de")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -198,7 +204,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.size should be(1) labels.head should be(StringLiteralV2(value = "Neue Liste", language = Some("de"))) - val comments = received.list.listinfo.comments.stringLiterals + val comments: Seq[StringLiteralV2] = listInfo.comments.stringLiterals comments.isEmpty should be(true) val children = received.list.children @@ -213,12 +219,18 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val commentWithSpecialCharacter = "Neue \\\"Kommentar\\\"" val nameWithSpecialCharacter = "a new \\\"name\\\"" responderManager ! ListCreateRequestADM( - createRootNode = CreateNodeApiRequestADM( - projectIri = IMAGES_PROJECT_IRI, - name = Some(nameWithSpecialCharacter), - labels = Seq(StringLiteralV2(value = labelWithSpecialCharacter, language = Some("de"))), - comments = Seq(StringLiteralV2(value = commentWithSpecialCharacter, language = Some("de"))) - ).escape, + createRootNode = NodeCreatePayloadADM + .create( + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = labelWithSpecialCharacter, language = Some("de")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = commentWithSpecialCharacter, language = Some("de")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -319,13 +331,19 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to list - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = CreateNodeApiRequestADM( - parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some("first"), - labels = Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en"))), - comments = Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en"))) - ), + createChildNodeRequest = NodeCreatePayloadADM + .create( + parentNodeIri = Some(newListIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("first").fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -365,14 +383,20 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add second child to list in first position - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = CreateNodeApiRequestADM( - parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some("second"), - position = Some(0), - labels = Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en"))), - comments = Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en"))) - ), + createChildNodeRequest = NodeCreatePayloadADM + .create( + parentNodeIri = Some(newListIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("second").fold(e => throw e, v => v)), + position = Some(Position.create(0).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -412,13 +436,19 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to second child node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = CreateNodeApiRequestADM( - parentNodeIri = Some(secondChildIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some("third"), - labels = Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en"))), - comments = Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en"))) - ), + createChildNodeRequest = NodeCreatePayloadADM + .create( + parentNodeIri = Some(secondChildIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("third").fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -459,14 +489,20 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "not create a node if given new position is out of range" in { val givenPosition = 20 responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = CreateNodeApiRequestADM( - parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some("fourth"), - position = Some(givenPosition), - labels = Seq(StringLiteralV2(value = "New Fourth Child List Node Value", language = Some("en"))), - comments = Seq(StringLiteralV2(value = "New Fourth Child List Node Comment", language = Some("en"))) - ), + createChildNodeRequest = NodeCreatePayloadADM + .create( + parentNodeIri = Some(newListIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("fourth").fold(e => throw e, v => v)), + position = Some(Position.create(givenPosition).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID From c909a8ea06d1e19b646e718e2ed38c7f36718988 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 14 Oct 2021 14:23:57 +0200 Subject: [PATCH 05/32] many things happened, mainly add ChangeNodeInfoPayloadADM --- .../listsmessages/ListPayloadsADM.scala | 46 ++++++++++----- .../listsmessages/ListsMessagesADM.scala | 8 +-- .../responders/admin/ListsResponderADM.scala | 58 +++++++++++-------- .../admin/lists/NewListsRouteADMFeature.scala | 37 +++++++++++- .../admin/lists/OldListsRouteADMFeature.scala | 39 ++++++++++++- .../admin/lists/UpdateListItemsRouteADM.scala | 19 ++++-- .../sparql/admin/createNewListNode.scala.txt | 3 +- .../OldListsRouteADMFeatureE2ESpec.scala | 4 +- .../listsmessages/ListsMessagesADMSpec.scala | 26 ++++++--- .../admin/ListsResponderADMSpec.scala | 32 ++++++---- 10 files changed, 201 insertions(+), 71 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index 535f9e5ca2..5e3e741cb1 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -23,6 +23,27 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, // comments: Comments // ): ListCreatePayloadADM = new ListCreatePayloadADM(id, projectIri, name, labels, comments) {} //} +//sealed trait NodeCreatePayloadADM +//object NodeCreatePayloadADM { +// final case class CreateRootNodePayloadADM( +// id: Option[IRI] = None, +// parentNodeIri: Option[IRI] = None, +// projectIri: IRI, +// name: Option[Name] = None, +// position: Option[Position] = None, +// labels: Labels, +// comments: Comments +// ) extends NodeCreatePayloadADM +// final case class CreateChildNodePayloadADM( +// id: Option[IRI] = None, +// parentNodeIri: Option[IRI] = None, +// projectIri: IRI, +// name: Option[Name] = None, +// position: Option[Position] = None, +// labels: Labels, +// comments: Option[Comments] = None +// ) extends NodeCreatePayloadADM +//} /** * Node creation payload @@ -49,7 +70,7 @@ object NodeCreatePayloadADM { ): NodeCreatePayloadADM = new NodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, labels, comments) {} } -sealed abstract case class NodeChangePayloadADM private ( +final case class ChangeNodeInfoPayloadADM( listIri: IRI, projectIri: IRI, hasRootNode: Option[IRI] = None, @@ -59,15 +80,14 @@ sealed abstract case class NodeChangePayloadADM private ( comments: Option[Comments] = None ) -object NodeChangePayloadADM { - def create( - listIri: IRI, - projectIri: IRI, - hasRootNode: Option[IRI], - position: Option[Position], - name: Option[Name], - labels: Option[Labels], - comments: Option[Comments] - ): NodeChangePayloadADM = - new NodeChangePayloadADM(listIri, projectIri, hasRootNode, position, name, labels, comments) {} -} +final case class ChangeNodeNamePayloadADM( + name: Name +) + +final case class ChangeNodeLabelsPayloadADM( + labels: Labels +) + +final case class ChangeNodeCommentsPayloadADM( + comments: Comments +) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index bb562a2627..cdf58c4c12 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -347,7 +347,7 @@ case class ListCreateRequestADM( */ case class NodeInfoChangeRequestADM( listIri: IRI, - changeNodeRequest: ChangeNodeInfoApiRequestADM, + changeNodeRequest: ChangeNodeInfoPayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -401,7 +401,7 @@ case class ListChildNodeCreateRequestADM( */ case class NodeNameChangeRequestADM( nodeIri: IRI, - changeNodeNameRequest: ChangeNodeNameApiRequestADM, + changeNodeNameRequest: ChangeNodeNamePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -418,7 +418,7 @@ case class NodeNameChangeRequestADM( */ case class NodeLabelsChangeRequestADM( nodeIri: IRI, - changeNodeLabelsRequest: ChangeNodeLabelsApiRequestADM, + changeNodeLabelsRequest: ChangeNodeLabelsPayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -435,7 +435,7 @@ case class NodeLabelsChangeRequestADM( */ case class NodeCommentsChangeRequestADM( nodeIri: IRI, - changeNodeCommentsRequest: ChangeNodeCommentsApiRequestADM, + changeNodeCommentsRequest: ChangeNodeCommentsPayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 910c58c418..ed0cff0825 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -36,6 +36,7 @@ import org.knora.webapi.messages.util.{KnoraSystemInstances, ResponderData} import org.knora.webapi.messages.{OntologyConstants, SmartIri} import org.knora.webapi.responders.Responder.handleUnexpectedMessage import org.knora.webapi.responders.{IriLocker, Responder} +import org.knora.webapi.messages.admin.responder.valueObjects.Name import scala.annotation.tailrec import scala.concurrent.Future @@ -850,6 +851,13 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde featureFactoryConfig: FeatureFactoryConfig ): Future[IRI] = { +// val payload = createNodeRequest match { +// case value: NodeCreatePayloadADM.CreateRootNodePayloadADM => value +// case value: NodeCreatePayloadADM.CreateChildNodePayloadADM => value +// } +// +// def createChild() + def getPositionOfNewChild(children: Seq[ListChildNodeADM]): Int = { if (createNodeRequest.position.get.value > children.size) { val givenPosition = createNodeRequest.position.get @@ -936,7 +944,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde /* verify that the list node name is unique for the project */ projectUniqueNodeName <- listNodeNameIsProjectUnique( createNodeRequest.projectIri, - Some(createNodeRequest.name.get.value) //TODO: dirty solution? + createNodeRequest.name //TODO: dirty solution? ) _ = if (!projectUniqueNodeName) { val escapedName = createNodeRequest.name.get.value @@ -983,6 +991,8 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde ) .toString + _ = println("XXXXX", createNewListSparqlString) + _ <- (storeManager ? SparqlUpdateRequest(createNewListSparqlString)).mapTo[SparqlUpdateResponse] } yield newListNodeIri } @@ -1001,6 +1011,8 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde apiRequestID: UUID ): Future[ListGetResponseADM] = { + println("XXXXXXX") + /** * The actual task run with an IRI lock. */ @@ -1052,7 +1064,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeInfoChangeRequest( nodeIri: IRI, - changeNodeRequest: ChangeNodeInfoApiRequestADM, + changeNodeRequest: ChangeNodeInfoPayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = { @@ -1060,12 +1072,12 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde def verifyUpdatedNode(updatedNode: ListNodeInfoADM): Unit = { if (changeNodeRequest.labels.nonEmpty) { - if (updatedNode.getLabels.stringLiterals.diff(changeNodeRequest.labels.get).nonEmpty) + if (updatedNode.getLabels.stringLiterals.diff(changeNodeRequest.labels.get.value).nonEmpty) throw UpdateNotPerformedException("Lists's 'labels' where not updated. Please report this as a possible bug.") } if (changeNodeRequest.comments.nonEmpty) { - if (updatedNode.getComments.stringLiterals.diff(changeNodeRequest.comments.get).nonEmpty) + if (updatedNode.getComments.stringLiterals.diff(changeNodeRequest.comments.get.value).nonEmpty) throw UpdateNotPerformedException("List's 'comments' was not updated. Please report this as a possible bug.") } @@ -1080,7 +1092,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeInfoChangeTask( nodeIri: IRI, - changeNodeRequest: ChangeNodeInfoApiRequestADM, + changeNodeRequest: ChangeNodeInfoPayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = @@ -1196,7 +1208,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeNameChangeRequest( nodeIri: IRI, - changeNodeNameRequest: ChangeNodeNameApiRequestADM, + changeNodeNameRequest: ChangeNodeNamePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1211,7 +1223,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeNameChangeTask( nodeIri: IRI, - changeNodeNameRequest: ChangeNodeNameApiRequestADM, + changeNodeNameRequest: ChangeNodeNamePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1226,7 +1238,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } changeNodeNameSparqlString <- getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest = ChangeNodeInfoApiRequestADM( + changeNodeInfoRequest = ChangeNodeInfoPayloadADM( listIri = nodeIri, projectIri = projectIri, name = Some(changeNodeNameRequest.name) @@ -1282,14 +1294,14 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeLabelsChangeRequest( nodeIri: IRI, - changeNodeLabelsRequest: ChangeNodeLabelsApiRequestADM, + changeNodeLabelsRequest: ChangeNodeLabelsPayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = { def verifyUpdatedNode(updatedNode: ListNodeInfoADM): Unit = - if (updatedNode.getLabels.stringLiterals.diff(changeNodeLabelsRequest.labels).nonEmpty) + if (updatedNode.getLabels.stringLiterals.diff(changeNodeLabelsRequest.labels.value).nonEmpty) throw UpdateNotPerformedException("Node's 'labels' were not updated. Please report this as a possible bug.") /** @@ -1297,7 +1309,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeLabelsChangeTask( nodeIri: IRI, - changeNodeLabelsRequest: ChangeNodeLabelsApiRequestADM, + changeNodeLabelsRequest: ChangeNodeLabelsPayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1312,7 +1324,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde throw ForbiddenException(LIST_CHANGE_PERMISSION_ERROR) } changeNodeLabelsSparqlString <- getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest = ChangeNodeInfoApiRequestADM( + changeNodeInfoRequest = ChangeNodeInfoPayloadADM( listIri = nodeIri, projectIri = projectIri, labels = Some(changeNodeLabelsRequest.labels) @@ -1367,13 +1379,13 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeCommentsChangeRequest( nodeIri: IRI, - changeNodeCommentsRequest: ChangeNodeCommentsApiRequestADM, + changeNodeCommentsRequest: ChangeNodeCommentsPayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = { def verifyUpdatedNode(updatedNode: ListNodeInfoADM): Unit = - if (updatedNode.getComments.stringLiterals.diff(changeNodeCommentsRequest.comments).nonEmpty) + if (updatedNode.getComments.stringLiterals.diff(changeNodeCommentsRequest.comments.value).nonEmpty) throw UpdateNotPerformedException("Node's 'comments' were not updated. Please report this as a possible bug.") /** @@ -1381,7 +1393,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeCommentsChangeTask( nodeIri: IRI, - changeNodeCommentsRequest: ChangeNodeCommentsApiRequestADM, + changeNodeCommentsRequest: ChangeNodeCommentsPayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1397,7 +1409,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } changeNodeCommentsSparqlString <- getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest = ChangeNodeInfoApiRequestADM( + changeNodeInfoRequest = ChangeNodeInfoPayloadADM( listIri = nodeIri, projectIri = projectIri, comments = Some(changeNodeCommentsRequest.comments) @@ -2081,15 +2093,15 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @param listNodeName the list node name. * @return a [[Boolean]]. */ - private def listNodeNameIsProjectUnique(projectIri: IRI, listNodeName: Option[String]): Future[Boolean] = + private def listNodeNameIsProjectUnique(projectIri: IRI, listNodeName: Option[Name]): Future[Boolean] = listNodeName match { case Some(name) => for { askString <- Future( org.knora.webapi.messages.twirl.queries.sparql.admin.txt .checkListNodeNameIsProjectUnique( - projectIri = projectIri, - listNodeName = name + projectIri, + listNodeName = name.value ) .toString ) @@ -2111,7 +2123,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @return a [[String]]. */ private def getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest: ChangeNodeInfoApiRequestADM, + changeNodeInfoRequest: ChangeNodeInfoPayloadADM, featureFactoryConfig: FeatureFactoryConfig ): Future[String] = for { @@ -2157,11 +2169,11 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde nodeIri = changeNodeInfoRequest.listIri, hasOldName = hasOldName, isRootNode = isRootNode, - maybeName = changeNodeInfoRequest.name, + maybeName = changeNodeInfoRequest.name.map(_.value), projectIri = changeNodeInfoRequest.projectIri, listClassIri = OntologyConstants.KnoraBase.ListNode, - maybeLabels = changeNodeInfoRequest.labels, - maybeComments = changeNodeInfoRequest.comments + maybeLabels = changeNodeInfoRequest.labels.map(_.value), + maybeComments = changeNodeInfoRequest.comments.map(_.value) ) .toString } yield changeNodeInfoSparqlString diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 6f71a8c2fa..bfcbaefd88 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -318,11 +318,46 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val listIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) + val maybeName: Option[Name] = apiRequest.name match { + case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybePosition: Option[Position] = apiRequest.position match { + case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybeLabels: Option[Labels] = apiRequest.labels match { + case Some(value) => Some(Labels.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybeComments: Option[Comments] = apiRequest.comments match { + case Some(value) => Some(Comments.create(value).fold(e => throw e, v => v)) + case None => None + } + + val changeNodeInfoPayloadADM: ChangeNodeInfoPayloadADM = ChangeNodeInfoPayloadADM( + listIri, + projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + hasRootNode = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.hasRootNode, + throw BadRequestException(s"Invalid root node IRI") + ), + position = maybePosition, + name = maybeName, + labels = maybeLabels, + comments = maybeComments + ) + val requestMessage: Future[NodeInfoChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) } yield NodeInfoChangeRequestADM( + //TODO: why "listIri" property is doubled - here and inside "changeNodeRequest" listIri = listIri, - changeNodeRequest = apiRequest, + changeNodeRequest = changeNodeInfoPayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 7881b3ad71..c2e26c5537 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -157,6 +157,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) ) + println("YYYYY", nodeCreatePayloadADM) + val requestMessage: Future[ListCreateRequestADM] = for { requestingUser <- getUserADM( requestContext = requestContext, @@ -250,11 +252,46 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) entity(as[ChangeNodeInfoApiRequestADM]) { apiRequest => requestContext => val listIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) + + val maybeName: Option[Name] = apiRequest.name match { + case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybePosition: Option[Position] = apiRequest.position match { + case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybeLabels: Option[Labels] = apiRequest.labels match { + case Some(value) => Some(Labels.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybeComments: Option[Comments] = apiRequest.comments match { + case Some(value) => Some(Comments.create(value).fold(e => throw e, v => v)) + case None => None + } + + val changeNodeInfoPayloadADM: ChangeNodeInfoPayloadADM = ChangeNodeInfoPayloadADM( + listIri, + projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + hasRootNode = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.hasRootNode, + throw BadRequestException(s"Invalid root node IRI") + ), + position = maybePosition, + name = maybeName, + labels = maybeLabels, + comments = maybeComments + ) + val requestMessage: Future[NodeInfoChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) } yield NodeInfoChangeRequestADM( listIri = listIri, - changeNodeRequest = apiRequest, + changeNodeRequest = changeNodeInfoPayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala index da872f55ae..6de2ef55f6 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala @@ -20,14 +20,15 @@ package org.knora.webapi.routing.admin.lists import java.util.UUID - import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{PathMatcher, Route} import io.swagger.annotations._ + import javax.ws.rs.Path import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} import org.knora.webapi.messages.admin.responder.listsmessages._ +import org.knora.webapi.messages.admin.responder.valueObjects.{Name, Labels, Comments} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -89,11 +90,15 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) val nodeIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) + val namePayload: ChangeNodeNamePayloadADM = + ChangeNodeNamePayloadADM(Name.create(apiRequest.name).fold(e => throw e, v => v)) + val requestMessage: Future[NodeNameChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) } yield NodeNameChangeRequestADM( nodeIri = nodeIri, - changeNodeNameRequest = apiRequest, +// payload for name + changeNodeNameRequest = namePayload, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -145,11 +150,14 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) val nodeIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) + val labelsPayload: ChangeNodeLabelsPayloadADM = + ChangeNodeLabelsPayloadADM(Labels.create(apiRequest.labels).fold(e => throw e, v => v)) + val requestMessage: Future[NodeLabelsChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) } yield NodeLabelsChangeRequestADM( nodeIri = nodeIri, - changeNodeLabelsRequest = apiRequest, + changeNodeLabelsRequest = labelsPayload, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -201,11 +209,14 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) val nodeIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) + val commentsPayload: ChangeNodeCommentsPayloadADM = + ChangeNodeCommentsPayloadADM(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) + val requestMessage: Future[NodeCommentsChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) } yield NodeCommentsChangeRequestADM( nodeIri = nodeIri, - changeNodeCommentsRequest = apiRequest, + changeNodeCommentsRequest = commentsPayload, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt index bd3a868dec..51908c6b06 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt @@ -47,7 +47,7 @@ position: Option[Int], maybeName: Option[String], maybeLabels: Seq[StringLiteralV2], - maybeComments: Seq[StringLiteralV2] //this can be changed to maybeDescriptions + maybeComments: Seq[StringLiteralV2] ) PREFIX xsd: @@ -91,7 +91,6 @@ INSERT { @if(maybeComments.nonEmpty) { @for(comment <- maybeComments) { @if(comment.language.nonEmpty) { - // rdfs:comment can't be changed to descriptions because it breaks the data ?nodeIri rdfs:comment """@comment.value"""@@@{comment.language.get} . } else { ?nodeIri rdfs:comment """@comment.value"""^^xsd:string . diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala index c0a5816dfb..24b3aa53ca 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala @@ -107,7 +107,7 @@ class OldListsRouteADMFeatureE2ESpec Get(baseApiUrl + s"/admin/lists") ~> addCredentials(BasicHttpCredentials(rootCreds.email, rootCreds.password)) val response: HttpResponse = singleAwaitingRequest(request) - // println(s"response: ${response.toString}") +// println(s"response: ${response.toString}") response.status should be(StatusCodes.OK) @@ -299,7 +299,7 @@ class OldListsRouteADMFeatureE2ESpec | "id": "${SharedTestDataADM.customListIRI}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "New list with a custom IRI", "language": "en"}], - | "comments": [] + | "comments": [{ "value": "XXX", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index badfc02f15..1d228c15d8 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -413,20 +413,28 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li val caught = intercept[ForbiddenException]( NodeInfoChangeRequestADM( listIri = exampleListIri, - changeNodeRequest = ChangeNodeInfoApiRequestADM( + changeNodeRequest = ChangeNodeInfoPayloadADM( listIri = exampleListIri, projectIri = IMAGES_PROJECT_IRI, labels = Some( - Seq( - StringLiteralV2(value = "Neue geänderte Liste", language = Some("de")), - StringLiteralV2(value = "Changed list", language = Some("en")) - ) + Labels + .create( + Seq( + StringLiteralV2(value = "Neue geänderte Liste", language = Some("de")), + StringLiteralV2(value = "Changed List", language = Some("en")) + ) + ) + .fold(e => throw e, v => v) ), comments = Some( - Seq( - StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), - StringLiteralV2(value = "New comment", language = Some("en")) - ) + Comments + .create( + Seq( + StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), + StringLiteralV2(value = "New Comment", language = Some("en")) + ) + ) + .fold(e => throw e, v => v) ) ), featureFactoryConfig = defaultFeatureFactoryConfig, diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 33a1bad175..970113c139 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -261,21 +261,29 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "update basic list information" in { val changeNodeInfoRequest = NodeInfoChangeRequestADM( listIri = newListIri.get, - changeNodeRequest = ChangeNodeInfoApiRequestADM( + changeNodeRequest = ChangeNodeInfoPayloadADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, - name = Some("updated name"), + name = Some(Name.create("updated name").fold(e => throw e, v => v)), labels = Some( - Seq( - StringLiteralV2(value = "Neue geänderte Liste", language = Some("de")), - StringLiteralV2(value = "Changed List", language = Some("en")) - ) + Labels + .create( + Seq( + StringLiteralV2(value = "Neue geänderte Liste", language = Some("de")), + StringLiteralV2(value = "Changed List", language = Some("en")) + ) + ) + .fold(e => throw e, v => v) ), comments = Some( - Seq( - StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), - StringLiteralV2(value = "New Comment", language = Some("en")) - ) + Comments + .create( + Seq( + StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), + StringLiteralV2(value = "New Comment", language = Some("en")) + ) + ) + .fold(e => throw e, v => v) ) ), featureFactoryConfig = defaultFeatureFactoryConfig, @@ -311,10 +319,10 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "not update basic list information if name is duplicate" in { responderManager ! NodeInfoChangeRequestADM( listIri = newListIri.get, - changeNodeRequest = ChangeNodeInfoApiRequestADM( + changeNodeRequest = ChangeNodeInfoPayloadADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, - name = Some("sommer") + name = Some(Name.create("sommer").fold(e => throw e, v => v)) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, From b95f56655063dc4717c946a81e729ff31c1b6ae3 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 14 Oct 2021 14:46:01 +0200 Subject: [PATCH 06/32] update NodeCreatePayloadADM class --- .../listsmessages/ListPayloadsADM.scala | 14 +- .../admin/lists/NewListsRouteADMFeature.scala | 12 +- .../admin/lists/OldListsRouteADMFeature.scala | 4 +- .../listsmessages/ListsMessagesADMSpec.scala | 69 +++++----- .../admin/ListsResponderADMSpec.scala | 129 +++++++++--------- 5 files changed, 99 insertions(+), 129 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index 5e3e741cb1..de3943eca7 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -48,7 +48,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, /** * Node creation payload */ -sealed abstract case class NodeCreatePayloadADM private ( +final case class NodeCreatePayloadADM( id: Option[IRI] = None, parentNodeIri: Option[IRI] = None, projectIri: IRI, @@ -58,18 +58,6 @@ sealed abstract case class NodeCreatePayloadADM private ( comments: Comments ) -object NodeCreatePayloadADM { - def create( - id: Option[IRI] = None, - parentNodeIri: Option[IRI] = None, - projectIri: IRI, - name: Option[Name] = None, - position: Option[Position] = None, - labels: Labels, - comments: Comments - ): NodeCreatePayloadADM = new NodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, labels, comments) {} -} - final case class ChangeNodeInfoPayloadADM( listIri: IRI, projectIri: IRI, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index bfcbaefd88..8e38932260 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -161,22 +161,12 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) case None => None } -// val listCreatePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM.create( -// id = stringFormatter -// .validateAndEscapeOptionalIri(apiRequest.id, throw BadRequestException(s"Invalid custom list IRI")), -// projectIri = stringFormatter -// .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), -// name = maybeName, -// labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), -// comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) -// ) - val maybePosition: Option[Position] = apiRequest.position match { case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) case None => None } - val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM.create( + val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( apiRequest.id, throw BadRequestException(s"Invalid custom node IRI") diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index c2e26c5537..e2ab974f7f 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -140,7 +140,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM.create( + val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( apiRequest.id, throw BadRequestException(s"Invalid custom node IRI") @@ -352,7 +352,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM.create( + val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( apiRequest.id, throw BadRequestException(s"Invalid custom node IRI") diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index 1d228c15d8..bd0b66e87e 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -146,17 +146,16 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'ForbiddenException' if user requesting `ListCreateApiRequestADM` is not system or project admin" in { val caught = intercept[ForbiddenException]( ListCreateRequestADM( - createRootNode = NodeCreatePayloadADM - .create( - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - labels = Labels - .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "Neuer Kommentar", language = Some("de")))) - .fold(e => throw e, v => v) - ), + createRootNode = NodeCreatePayloadADM( + projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, + labels = Labels + .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "Neuer Kommentar", language = Some("de")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser02, apiRequestID = UUID.randomUUID() @@ -365,18 +364,17 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'ForbiddenException' if user requesting `createChildNodeRequest` is not system or project admin" in { val caught = intercept[ForbiddenException]( ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM - .create( - parentNodeIri = Some(exampleListIri), - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - labels = Labels - .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) - .fold(e => throw e, v => v) - ), + createChildNodeRequest = NodeCreatePayloadADM( + parentNodeIri = Some(exampleListIri), + projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, + labels = Labels + .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser02, apiRequestID = UUID.randomUUID() @@ -388,19 +386,18 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'BadRequestException' if invalid position given in payload of `createChildNodeRequest`" in { val caught = intercept[BadRequestException]( ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM - .create( - parentNodeIri = Some(exampleListIri), - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - position = Some(Position.create(-3).fold(e => throw e, v => v)), - labels = Labels - .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) - .fold(e => throw e, v => v) - ), + createChildNodeRequest = NodeCreatePayloadADM( + parentNodeIri = Some(exampleListIri), + projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, + position = Some(Position.create(-3).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 970113c139..8ce8ab0e1b 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -177,7 +177,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "used to modify lists" should { "create a list" in { responderManager ! ListCreateRequestADM( - createRootNode = NodeCreatePayloadADM.create( + createRootNode = NodeCreatePayloadADM( projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("neuelistename").fold(e => throw e, v => v)), labels = Labels @@ -219,18 +219,17 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val commentWithSpecialCharacter = "Neue \\\"Kommentar\\\"" val nameWithSpecialCharacter = "a new \\\"name\\\"" responderManager ! ListCreateRequestADM( - createRootNode = NodeCreatePayloadADM - .create( - projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), - labels = Labels - .create(Seq(StringLiteralV2(value = labelWithSpecialCharacter, language = Some("de")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = commentWithSpecialCharacter, language = Some("de")))) - .fold(e => throw e, v => v) - ), + createRootNode = NodeCreatePayloadADM( + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = labelWithSpecialCharacter, language = Some("de")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = commentWithSpecialCharacter, language = Some("de")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -339,19 +338,18 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to list - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM - .create( - parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("first").fold(e => throw e, v => v)), - labels = Labels - .create(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) - ), + createChildNodeRequest = NodeCreatePayloadADM( + parentNodeIri = Some(newListIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("first").fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -391,20 +389,19 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add second child to list in first position - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM - .create( - parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("second").fold(e => throw e, v => v)), - position = Some(Position.create(0).fold(e => throw e, v => v)), - labels = Labels - .create(Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) - ), + createChildNodeRequest = NodeCreatePayloadADM( + parentNodeIri = Some(newListIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("second").fold(e => throw e, v => v)), + position = Some(Position.create(0).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -444,19 +441,18 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to second child node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM - .create( - parentNodeIri = Some(secondChildIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("third").fold(e => throw e, v => v)), - labels = Labels - .create(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) - ), + createChildNodeRequest = NodeCreatePayloadADM( + parentNodeIri = Some(secondChildIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("third").fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -497,20 +493,19 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "not create a node if given new position is out of range" in { val givenPosition = 20 responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM - .create( - parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("fourth").fold(e => throw e, v => v)), - position = Some(Position.create(givenPosition).fold(e => throw e, v => v)), - labels = Labels - .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Value", language = Some("en")))) - .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) - ), + createChildNodeRequest = NodeCreatePayloadADM( + parentNodeIri = Some(newListIri.get), + projectIri = IMAGES_PROJECT_IRI, + name = Some(Name.create("fourth").fold(e => throw e, v => v)), + position = Some(Position.create(givenPosition).fold(e => throw e, v => v)), + labels = Labels + .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Value", language = Some("en")))) + .fold(e => throw e, v => v), + // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] + comments = Comments + .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID From aa2672af9ca0a0ad21271e6d722d7f2e09d0b11c Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 14 Oct 2021 14:51:38 +0200 Subject: [PATCH 07/32] refactor list payloads --- .../listsmessages/ListPayloadsADM.scala | 40 ++++++++----------- .../listsmessages/ListsMessagesADM.scala | 8 ++-- .../responders/admin/ListsResponderADM.scala | 24 +++++------ .../admin/lists/NewListsRouteADMFeature.scala | 2 +- .../admin/lists/OldListsRouteADMFeature.scala | 2 +- .../admin/lists/UpdateListItemsRouteADM.scala | 12 +++--- .../listsmessages/ListsMessagesADMSpec.scala | 2 +- .../admin/ListsResponderADMSpec.scala | 4 +- 8 files changed, 43 insertions(+), 51 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index de3943eca7..cddaf920f5 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -3,26 +3,6 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} -///** -// * List payload -// */ -//sealed abstract case class ListCreatePayloadADM private ( -// id: Option[IRI] = None, -// projectIri: IRI, -// name: Option[Name] = None, -// labels: Labels, -// comments: Comments -//) -// -//object ListCreatePayloadADM { -// def create( -// id: Option[IRI], -// projectIri: IRI, -// name: Option[Name], -// labels: Labels, -// comments: Comments -// ): ListCreatePayloadADM = new ListCreatePayloadADM(id, projectIri, name, labels, comments) {} -//} //sealed trait NodeCreatePayloadADM //object NodeCreatePayloadADM { // final case class CreateRootNodePayloadADM( @@ -58,7 +38,10 @@ final case class NodeCreatePayloadADM( comments: Comments ) -final case class ChangeNodeInfoPayloadADM( +/** + * Node Info update payload + */ +final case class NodeInfoChangePayloadADM( listIri: IRI, projectIri: IRI, hasRootNode: Option[IRI] = None, @@ -68,14 +51,23 @@ final case class ChangeNodeInfoPayloadADM( comments: Option[Comments] = None ) -final case class ChangeNodeNamePayloadADM( +/** + * Node Name update payload + */ +final case class NodeNameChangePayloadADM( name: Name ) -final case class ChangeNodeLabelsPayloadADM( +/** + * Node Labels update payload + */ +final case class NodeLabelsChangePayloadADM( labels: Labels ) -final case class ChangeNodeCommentsPayloadADM( +/** + * Node Comments update payload + */ +final case class NodeCommentsChangePayloadADM( comments: Comments ) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index cdf58c4c12..07d9b76249 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -347,7 +347,7 @@ case class ListCreateRequestADM( */ case class NodeInfoChangeRequestADM( listIri: IRI, - changeNodeRequest: ChangeNodeInfoPayloadADM, + changeNodeRequest: NodeInfoChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -401,7 +401,7 @@ case class ListChildNodeCreateRequestADM( */ case class NodeNameChangeRequestADM( nodeIri: IRI, - changeNodeNameRequest: ChangeNodeNamePayloadADM, + changeNodeNameRequest: NodeNameChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -418,7 +418,7 @@ case class NodeNameChangeRequestADM( */ case class NodeLabelsChangeRequestADM( nodeIri: IRI, - changeNodeLabelsRequest: ChangeNodeLabelsPayloadADM, + changeNodeLabelsRequest: NodeLabelsChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -435,7 +435,7 @@ case class NodeLabelsChangeRequestADM( */ case class NodeCommentsChangeRequestADM( nodeIri: IRI, - changeNodeCommentsRequest: ChangeNodeCommentsPayloadADM, + changeNodeCommentsRequest: NodeCommentsChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index ed0cff0825..2c412ef351 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -1064,7 +1064,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeInfoChangeRequest( nodeIri: IRI, - changeNodeRequest: ChangeNodeInfoPayloadADM, + changeNodeRequest: NodeInfoChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = { @@ -1092,7 +1092,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeInfoChangeTask( nodeIri: IRI, - changeNodeRequest: ChangeNodeInfoPayloadADM, + changeNodeRequest: NodeInfoChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = @@ -1208,7 +1208,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeNameChangeRequest( nodeIri: IRI, - changeNodeNameRequest: ChangeNodeNamePayloadADM, + changeNodeNameRequest: NodeNameChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1223,7 +1223,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeNameChangeTask( nodeIri: IRI, - changeNodeNameRequest: ChangeNodeNamePayloadADM, + changeNodeNameRequest: NodeNameChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1238,7 +1238,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } changeNodeNameSparqlString <- getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest = ChangeNodeInfoPayloadADM( + changeNodeInfoRequest = NodeInfoChangePayloadADM( listIri = nodeIri, projectIri = projectIri, name = Some(changeNodeNameRequest.name) @@ -1294,7 +1294,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeLabelsChangeRequest( nodeIri: IRI, - changeNodeLabelsRequest: ChangeNodeLabelsPayloadADM, + changeNodeLabelsRequest: NodeLabelsChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1309,7 +1309,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeLabelsChangeTask( nodeIri: IRI, - changeNodeLabelsRequest: ChangeNodeLabelsPayloadADM, + changeNodeLabelsRequest: NodeLabelsChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1324,7 +1324,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde throw ForbiddenException(LIST_CHANGE_PERMISSION_ERROR) } changeNodeLabelsSparqlString <- getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest = ChangeNodeInfoPayloadADM( + changeNodeInfoRequest = NodeInfoChangePayloadADM( listIri = nodeIri, projectIri = projectIri, labels = Some(changeNodeLabelsRequest.labels) @@ -1379,7 +1379,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ private def nodeCommentsChangeRequest( nodeIri: IRI, - changeNodeCommentsRequest: ChangeNodeCommentsPayloadADM, + changeNodeCommentsRequest: NodeCommentsChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1393,7 +1393,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde */ def nodeCommentsChangeTask( nodeIri: IRI, - changeNodeCommentsRequest: ChangeNodeCommentsPayloadADM, + changeNodeCommentsRequest: NodeCommentsChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -1409,7 +1409,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } changeNodeCommentsSparqlString <- getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest = ChangeNodeInfoPayloadADM( + changeNodeInfoRequest = NodeInfoChangePayloadADM( listIri = nodeIri, projectIri = projectIri, comments = Some(changeNodeCommentsRequest.comments) @@ -2123,7 +2123,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @return a [[String]]. */ private def getUpdateNodeInfoSparqlStatement( - changeNodeInfoRequest: ChangeNodeInfoPayloadADM, + changeNodeInfoRequest: NodeInfoChangePayloadADM, featureFactoryConfig: FeatureFactoryConfig ): Future[String] = for { diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 8e38932260..18ab0a2cfe 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -328,7 +328,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val changeNodeInfoPayloadADM: ChangeNodeInfoPayloadADM = ChangeNodeInfoPayloadADM( + val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, projectIri = stringFormatter .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index e2ab974f7f..9ea8c19a91 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -273,7 +273,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val changeNodeInfoPayloadADM: ChangeNodeInfoPayloadADM = ChangeNodeInfoPayloadADM( + val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, projectIri = stringFormatter .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala index 6de2ef55f6..a8ffc53f8a 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala @@ -90,8 +90,8 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) val nodeIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) - val namePayload: ChangeNodeNamePayloadADM = - ChangeNodeNamePayloadADM(Name.create(apiRequest.name).fold(e => throw e, v => v)) + val namePayload: NodeNameChangePayloadADM = + NodeNameChangePayloadADM(Name.create(apiRequest.name).fold(e => throw e, v => v)) val requestMessage: Future[NodeNameChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) @@ -150,8 +150,8 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) val nodeIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) - val labelsPayload: ChangeNodeLabelsPayloadADM = - ChangeNodeLabelsPayloadADM(Labels.create(apiRequest.labels).fold(e => throw e, v => v)) + val labelsPayload: NodeLabelsChangePayloadADM = + NodeLabelsChangePayloadADM(Labels.create(apiRequest.labels).fold(e => throw e, v => v)) val requestMessage: Future[NodeLabelsChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) @@ -209,8 +209,8 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) val nodeIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) - val commentsPayload: ChangeNodeCommentsPayloadADM = - ChangeNodeCommentsPayloadADM(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) + val commentsPayload: NodeCommentsChangePayloadADM = + NodeCommentsChangePayloadADM(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) val requestMessage: Future[NodeCommentsChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index bd0b66e87e..4fdc7ad9f7 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -410,7 +410,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li val caught = intercept[ForbiddenException]( NodeInfoChangeRequestADM( listIri = exampleListIri, - changeNodeRequest = ChangeNodeInfoPayloadADM( + changeNodeRequest = NodeInfoChangePayloadADM( listIri = exampleListIri, projectIri = IMAGES_PROJECT_IRI, labels = Some( diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 8ce8ab0e1b..42691a19a2 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -260,7 +260,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "update basic list information" in { val changeNodeInfoRequest = NodeInfoChangeRequestADM( listIri = newListIri.get, - changeNodeRequest = ChangeNodeInfoPayloadADM( + changeNodeRequest = NodeInfoChangePayloadADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("updated name").fold(e => throw e, v => v)), @@ -318,7 +318,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "not update basic list information if name is duplicate" in { responderManager ! NodeInfoChangeRequestADM( listIri = newListIri.get, - changeNodeRequest = ChangeNodeInfoPayloadADM( + changeNodeRequest = NodeInfoChangePayloadADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("sommer").fold(e => throw e, v => v)) From 18e2d9244dc74e9217c505c41678ab8c22172a95 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 14 Oct 2021 15:53:18 +0200 Subject: [PATCH 08/32] WIP - fix tests --- .../responders/admin/ListsResponderADM.scala | 11 ++++++----- .../lists/OldListsRouteADMFeatureE2ESpec.scala | 2 +- .../responders/admin/ListsResponderADMSpec.scala | 15 +++++++++------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 2c412ef351..c354dc0fdf 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -858,15 +858,17 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde // // def createChild() + println("ZZZZZ", createNodeRequest) + def getPositionOfNewChild(children: Seq[ListChildNodeADM]): Int = { - if (createNodeRequest.position.get.value > children.size) { + if (createNodeRequest.position.exists(_.value > children.size)) { val givenPosition = createNodeRequest.position.get throw BadRequestException( s"Invalid position given $givenPosition, maximum allowed position is = ${children.size}." ) } - val position = if (createNodeRequest.position.isEmpty || createNodeRequest.position.exists(_.equals(-1))) { + val position = if (createNodeRequest.position.isEmpty || createNodeRequest.position.exists(_.value.equals(-1))) { children.size } else { createNodeRequest.position.get.value @@ -991,8 +993,6 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde ) .toString - _ = println("XXXXX", createNewListSparqlString) - _ <- (storeManager ? SparqlUpdateRequest(createNewListSparqlString)).mapTo[SparqlUpdateResponse] } yield newListNodeIri } @@ -1082,7 +1082,8 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } if (changeNodeRequest.name.nonEmpty) { - if (updatedNode.getName.nonEmpty && updatedNode.getName.get != changeNodeRequest.name.get) +// println("ZZZZZ", changeNodeRequest.name, updatedNode.getName) + if (updatedNode.getName.nonEmpty && updatedNode.getName.get != changeNodeRequest.name.get.value) throw UpdateNotPerformedException("List's 'name' was not updated. Please report this as a possible bug.") } } diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala index 24b3aa53ca..635edeff79 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala @@ -299,7 +299,7 @@ class OldListsRouteADMFeatureE2ESpec | "id": "${SharedTestDataADM.customListIRI}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "New list with a custom IRI", "language": "en"}], - | "comments": [{ "value": "XXX", "language": "en"}] + | "comments": [] |}""".stripMargin clientTestDataCollector.addFile( diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 42691a19a2..054b8023f5 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -205,7 +205,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.head should be(StringLiteralV2(value = "Neue Liste", language = Some("de"))) val comments: Seq[StringLiteralV2] = listInfo.comments.stringLiterals - comments.isEmpty should be(true) + comments.isEmpty should be(false) val children = received.list.children children.size should be(0) @@ -316,12 +316,13 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with } "not update basic list information if name is duplicate" in { + val name = Some(Name.create("sommer").fold(e => throw e, v => v)) responderManager ! NodeInfoChangeRequestADM( listIri = newListIri.get, changeNodeRequest = NodeInfoChangePayloadADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("sommer").fold(e => throw e, v => v)) + name = name ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -330,7 +331,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with expectMsg( Failure( DuplicateValueException( - "The name sommer is already used by a list inside the project http://rdfh.ch/projects/00FF." + s"The name ${name.value} is already used by a list inside the project http://rdfh.ch/projects/00FF." ) ) ) @@ -491,13 +492,13 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with } "not create a node if given new position is out of range" in { - val givenPosition = 20 + val givenPosition = Some(Position.create(20).fold(e => throw e, v => v)) responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = NodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("fourth").fold(e => throw e, v => v)), - position = Some(Position.create(givenPosition).fold(e => throw e, v => v)), + position = givenPosition, labels = Labels .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Value", language = Some("en")))) .fold(e => throw e, v => v), @@ -511,7 +512,9 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with apiRequestID = UUID.randomUUID ) expectMsg( - Failure(BadRequestException(s"Invalid position given ${givenPosition}, maximum allowed position is = 2.")) + Failure( + BadRequestException(s"Invalid position given ${givenPosition.value}, maximum allowed position is = 2.") + ) ) } } From 1f6b136174a47694510d4ed167b2398126d834bb Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 14 Oct 2021 16:29:12 +0200 Subject: [PATCH 09/32] fix tests --- .../responders/admin/ListsResponderADM.scala | 9 ++++----- .../admin/lists/OldListsRouteADMFeature.scala | 2 +- .../NewListsRoutesADMFeatureE2ESpec.scala | 20 +++++++++---------- .../OldListsRouteADMFeatureE2ESpec.scala | 20 +++++++++---------- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index c354dc0fdf..df47483a1b 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -858,7 +858,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde // // def createChild() - println("ZZZZZ", createNodeRequest) + println("ZZZZZ-createNode", createNodeRequest) def getPositionOfNewChild(children: Seq[ListChildNodeADM]): Int = { if (createNodeRequest.position.exists(_.value > children.size)) { @@ -946,7 +946,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde /* verify that the list node name is unique for the project */ projectUniqueNodeName <- listNodeNameIsProjectUnique( createNodeRequest.projectIri, - createNodeRequest.name //TODO: dirty solution? + createNodeRequest.name ) _ = if (!projectUniqueNodeName) { val escapedName = createNodeRequest.name.get.value @@ -987,7 +987,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde parentNodeIri = createNodeRequest.parentNodeIri, rootNodeIri = rootNodeIri, position = position, - maybeName = Some(createNodeRequest.name.get.value), //TODO: instead of this should be SPARQL updated? + maybeName = createNodeRequest.name.map(_.value), //TODO: still not sure if that's correct maybeLabels = createNodeRequest.labels.value, maybeComments = createNodeRequest.comments.value ) @@ -1011,7 +1011,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde apiRequestID: UUID ): Future[ListGetResponseADM] = { - println("XXXXXXX") + println("XXXXX-listCreateRequestADM") /** * The actual task run with an IRI lock. @@ -1082,7 +1082,6 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } if (changeNodeRequest.name.nonEmpty) { -// println("ZZZZZ", changeNodeRequest.name, updatedNode.getName) if (updatedNode.getName.nonEmpty && updatedNode.getName.get != changeNodeRequest.name.get.value) throw UpdateNotPerformedException("List's 'name' was not updated. Please report this as a possible bug.") } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 9ea8c19a91..cb4ed01c85 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -157,7 +157,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) ) - println("YYYYY", nodeCreatePayloadADM) + println("XXXXX", nodeCreatePayloadADM) val requestMessage: Future[ListCreateRequestADM] = for { requestingUser <- getUserADM( diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala index 0839b26244..3d4107c71f 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala @@ -309,7 +309,7 @@ class NewListsRouteADMFeatureE2ESpec | "id": "${SharedTestDataADM.customListIRI}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "New list with a custom IRI", "language": "en"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( @@ -362,7 +362,7 @@ class NewListsRouteADMFeatureE2ESpec | "id": "${SharedTestDataADM.customListIRI}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "New List", "language": "en"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -388,7 +388,7 @@ class NewListsRouteADMFeatureE2ESpec | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "name": "node with a custom IRI", | "labels": [{ "value": "New List Node", "language": "en"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( @@ -448,7 +448,7 @@ class NewListsRouteADMFeatureE2ESpec s"""{ | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( @@ -479,7 +479,7 @@ class NewListsRouteADMFeatureE2ESpec labels.head should be(StringLiteralV2(value = "Neue Liste", language = Some("de"))) val comments = receivedList.listinfo.comments.stringLiterals - comments.isEmpty should be(true) + comments.isEmpty should be(false) val children = receivedList.children children.size should be(0) @@ -504,7 +504,7 @@ class NewListsRouteADMFeatureE2ESpec |{ | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -525,7 +525,7 @@ class NewListsRouteADMFeatureE2ESpec |{ | "projectIri": "", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -541,7 +541,7 @@ class NewListsRouteADMFeatureE2ESpec |{ | "projectIri": "notvalidIRI", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -557,7 +557,7 @@ class NewListsRouteADMFeatureE2ESpec |{ | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -814,7 +814,7 @@ class NewListsRouteADMFeatureE2ESpec | "listIri": "${newListIri.get}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala index 635edeff79..a007bf0bde 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala @@ -299,7 +299,7 @@ class OldListsRouteADMFeatureE2ESpec | "id": "${SharedTestDataADM.customListIRI}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "New list with a custom IRI", "language": "en"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( @@ -349,7 +349,7 @@ class OldListsRouteADMFeatureE2ESpec | "id": "${SharedTestDataADM.customListIRI}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "New List", "language": "en"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -375,7 +375,7 @@ class OldListsRouteADMFeatureE2ESpec | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "name": "node with a custom IRI", | "labels": [{ "value": "New List Node", "language": "en"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( @@ -434,7 +434,7 @@ class OldListsRouteADMFeatureE2ESpec s"""{ | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( @@ -465,7 +465,7 @@ class OldListsRouteADMFeatureE2ESpec labels.head should be(StringLiteralV2(value = "Neue Liste", language = Some("de"))) val comments = receivedList.listinfo.comments.stringLiterals - comments.isEmpty should be(true) + comments.isEmpty should be(false) val children = receivedList.children children.size should be(0) @@ -490,7 +490,7 @@ class OldListsRouteADMFeatureE2ESpec |{ | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -511,7 +511,7 @@ class OldListsRouteADMFeatureE2ESpec |{ | "projectIri": "", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -526,7 +526,7 @@ class OldListsRouteADMFeatureE2ESpec |{ | "projectIri": "notvalidIRI", | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -541,7 +541,7 @@ class OldListsRouteADMFeatureE2ESpec |{ | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin @@ -784,7 +784,7 @@ class OldListsRouteADMFeatureE2ESpec | "listIri": "${newListIri.get}", | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", | "labels": [], - | "comments": [] + | "comments": [{ "value": "XXXXX", "language": "en"}] |} """.stripMargin From 327bb8ae1aa7cd6c1537aaed586fcf6d9783a88b Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 15 Oct 2021 15:42:03 +0200 Subject: [PATCH 10/32] separate root and child nodes creation --- .../listsmessages/ListPayloadsADM.scala | 56 +++----- .../listsmessages/ListsMessagesADM.scala | 40 +----- .../responders/admin/ListsResponderADM.scala | 125 ++++++++++------ .../admin/lists/NewListsRouteADMFeature.scala | 78 +++++++--- .../admin/lists/OldListsRouteADMFeature.scala | 59 ++++++-- .../admin/lists/UpdateListItemsRouteADM.scala | 9 +- .../admin/createNewChildListNode.scala.txt | 136 ++++++++++++++++++ ...la.txt => createNewRootListNode.scala.txt} | 8 +- .../UpdateListItemsRouteADME2ESpec.scala | 2 +- .../listsmessages/ListsMessagesADMSpec.scala | 29 ++-- .../admin/ListsResponderADMSpec.scala | 57 ++++---- 11 files changed, 413 insertions(+), 186 deletions(-) create mode 100644 webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt rename webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/{createNewListNode.scala.txt => createNewRootListNode.scala.txt} (95%) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index cddaf920f5..862368bf41 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -3,40 +3,30 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} -//sealed trait NodeCreatePayloadADM -//object NodeCreatePayloadADM { -// final case class CreateRootNodePayloadADM( -// id: Option[IRI] = None, -// parentNodeIri: Option[IRI] = None, -// projectIri: IRI, -// name: Option[Name] = None, -// position: Option[Position] = None, -// labels: Labels, -// comments: Comments -// ) extends NodeCreatePayloadADM -// final case class CreateChildNodePayloadADM( -// id: Option[IRI] = None, -// parentNodeIri: Option[IRI] = None, -// projectIri: IRI, -// name: Option[Name] = None, -// position: Option[Position] = None, -// labels: Labels, -// comments: Option[Comments] = None -// ) extends NodeCreatePayloadADM -//} - /** - * Node creation payload + * Root and Child Node creation payloads */ -final case class NodeCreatePayloadADM( - id: Option[IRI] = None, - parentNodeIri: Option[IRI] = None, - projectIri: IRI, - name: Option[Name] = None, - position: Option[Position] = None, - labels: Labels, - comments: Comments -) +sealed trait NodeCreatePayloadADM +object NodeCreatePayloadADM { + final case class RootNodeCreatePayloadADM( + id: Option[IRI] = None, + parentNodeIri: Option[IRI] = None, + projectIri: IRI, + name: Option[Name] = None, + position: Option[Position] = None, + labels: Labels, + comments: Comments + ) extends NodeCreatePayloadADM + final case class ChildNodeCreatePayloadADM( + id: Option[IRI] = None, + parentNodeIri: Option[IRI] = None, + projectIri: IRI, + name: Option[Name] = None, + position: Option[Position] = None, + labels: Labels, + comments: Option[Comments] = None + ) extends NodeCreatePayloadADM +} /** * Node Info update payload @@ -69,5 +59,5 @@ final case class NodeLabelsChangePayloadADM( * Node Comments update payload */ final case class NodeCommentsChangePayloadADM( - comments: Comments + comments: Option[Comments] ) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 07d9b76249..10095b4f7c 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -20,13 +20,13 @@ package org.knora.webapi.messages.admin.responder.listsmessages import java.util.UUID - import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import org.knora.webapi._ import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.ChildNodeCreatePayloadADM import org.knora.webapi.messages.admin.responder.usersmessages._ import org.knora.webapi.messages.admin.responder.{KnoraRequestADM, KnoraResponseADM} import org.knora.webapi.messages.store.triplestoremessages.{ @@ -326,15 +326,7 @@ case class ListCreateRequestADM( featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID -) extends ListsResponderRequestADM { - // check if the requesting user is allowed to perform operation - if ( - !requestingUser.permissions.isProjectAdmin(createRootNode.projectIri) && !requestingUser.permissions.isSystemAdmin - ) { - // not project or a system admin - throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) - } -} +) extends ListsResponderRequestADM /** * Request updating basic information of an existing node. @@ -351,18 +343,7 @@ case class NodeInfoChangeRequestADM( featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID -) extends ListsResponderRequestADM { - // check if the requesting user is allowed to perform operation - if ( - !requestingUser.permissions.isProjectAdmin( - changeNodeRequest.projectIri - ) && !requestingUser.permissions.isSystemAdmin - ) { - // not project or a system admin - throw ForbiddenException(LIST_CHANGE_PERMISSION_ERROR) - } - -} +) extends ListsResponderRequestADM /** * Request the creation of a new list node, root or child. @@ -373,22 +354,11 @@ case class NodeInfoChangeRequestADM( * @param apiRequestID the ID of the API request. */ case class ListChildNodeCreateRequestADM( - createChildNodeRequest: NodeCreatePayloadADM, + createChildNodeRequest: ChildNodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID -) extends ListsResponderRequestADM { - // check if the requesting user is allowed to perform operation - if ( - !requestingUser.permissions.isProjectAdmin( - createChildNodeRequest.projectIri - ) && !requestingUser.permissions.isSystemAdmin - ) { - // not project or a system admin - throw ForbiddenException(LIST_NODE_CREATE_PERMISSION_ERROR) - } - -} +) extends ListsResponderRequestADM /** * Request updating the name of an existing node. diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index df47483a1b..e1e59e772d 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -27,6 +27,10 @@ import org.knora.webapi.exceptions._ import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ + ChildNodeCreatePayloadADM, + RootNodeCreatePayloadADM +} import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectGetADM, ProjectIdentifierADM} import org.knora.webapi.messages.admin.responder.usersmessages._ @@ -851,29 +855,29 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde featureFactoryConfig: FeatureFactoryConfig ): Future[IRI] = { -// val payload = createNodeRequest match { -// case value: NodeCreatePayloadADM.CreateRootNodePayloadADM => value -// case value: NodeCreatePayloadADM.CreateChildNodePayloadADM => value -// } -// -// def createChild() - println("ZZZZZ-createNode", createNodeRequest) + val (id, parentNodeIri, projectIri, name, position) = createNodeRequest match { + case RootNodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, _, _) => + (id, parentNodeIri, projectIri, name, position) + case ChildNodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, _, _) => + (id, parentNodeIri, projectIri, name, position) + } + def getPositionOfNewChild(children: Seq[ListChildNodeADM]): Int = { - if (createNodeRequest.position.exists(_.value > children.size)) { - val givenPosition = createNodeRequest.position.get + if (position.exists(_.value > children.size)) { + val givenPosition = position.get throw BadRequestException( s"Invalid position given $givenPosition, maximum allowed position is = ${children.size}." ) } - val position = if (createNodeRequest.position.isEmpty || createNodeRequest.position.exists(_.value.equals(-1))) { + val newPosition = if (position.isEmpty || position.exists(_.value.equals(-1))) { children.size } else { - createNodeRequest.position.get.value + position.get.value } - position + newPosition } def getRootNodeIri(parentListNode: ListNodeADM): IRI = @@ -933,26 +937,26 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde for { /* Verify that the project exists by retrieving it. We need the project information so that we can calculate the data graph and IRI for the new node. */ maybeProject <- (responderManager ? ProjectGetADM( - identifier = ProjectIdentifierADM(maybeIri = Some(createNodeRequest.projectIri)), + identifier = ProjectIdentifierADM(maybeIri = Some(projectIri)), featureFactoryConfig = featureFactoryConfig, KnoraSystemInstances.Users.SystemUser )).mapTo[Option[ProjectADM]] project: ProjectADM = maybeProject match { case Some(project: ProjectADM) => project - case None => throw BadRequestException(s"Project '${createNodeRequest.projectIri}' not found.") + case None => throw BadRequestException(s"Project '${projectIri}' not found.") } /* verify that the list node name is unique for the project */ projectUniqueNodeName <- listNodeNameIsProjectUnique( - createNodeRequest.projectIri, - createNodeRequest.name + projectIri, + name ) _ = if (!projectUniqueNodeName) { - val escapedName = createNodeRequest.name.get.value + val escapedName = name.get.value val unescapedName = stringFormatter.fromSparqlEncodedString(escapedName) throw BadRequestException( - s"The node name ${unescapedName} is already used by a list inside the project ${createNodeRequest.projectIri}." + s"The node name ${unescapedName} is already used by a list inside the project ${projectIri}." ) } @@ -961,9 +965,9 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde // if parent node is known, find the root node of the list and the position of the new child node (position: Option[Int], rootNodeIri: Option[IRI]) <- - if (createNodeRequest.parentNodeIri.nonEmpty) { + if (parentNodeIri.nonEmpty) { getRootNodeAndPositionOfNewChild( - parentNodeIri = createNodeRequest.parentNodeIri.get, + parentNodeIri = parentNodeIri.get, dataNamedGraph = dataNamedGraph, featureFactoryConfig = featureFactoryConfig ) @@ -972,26 +976,63 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } // check the custom IRI; if not given, create an unused IRI - customListIri: Option[SmartIri] = createNodeRequest.id.map(iri => iri.toSmartIri) + customListIri: Option[SmartIri] = id.map(iri => iri.toSmartIri) maybeShortcode: String = project.shortcode newListNodeIri: IRI <- checkOrCreateEntityIri(customListIri, stringFormatter.makeRandomListIri(maybeShortcode)) - // Create the new list node - createNewListSparqlString = org.knora.webapi.messages.twirl.queries.sparql.admin.txt - .createNewListNode( - dataNamedGraph = dataNamedGraph, - triplestore = settings.triplestoreType, - listClassIri = OntologyConstants.KnoraBase.ListNode, - projectIri = createNodeRequest.projectIri, - nodeIri = newListNodeIri, - parentNodeIri = createNodeRequest.parentNodeIri, - rootNodeIri = rootNodeIri, - position = position, - maybeName = createNodeRequest.name.map(_.value), //TODO: still not sure if that's correct - maybeLabels = createNodeRequest.labels.value, - maybeComments = createNodeRequest.comments.value - ) - .toString + // Create the new list node depending on type + createNewListSparqlString: String = createNodeRequest match { + case NodeCreatePayloadADM.RootNodeCreatePayloadADM( + _, + parentNodeIri, + projectIri, + name, + position, + labels, + comments + ) => { + org.knora.webapi.messages.twirl.queries.sparql.admin.txt + .createNewRootListNode( + dataNamedGraph = dataNamedGraph, + triplestore = settings.triplestoreType, + listClassIri = OntologyConstants.KnoraBase.ListNode, + projectIri = projectIri, + nodeIri = newListNodeIri, + parentNodeIri = parentNodeIri, + rootNodeIri = rootNodeIri, + position = position.map(_.value), + maybeName = name.map(_.value), + maybeLabels = labels.value, + maybeComments = comments.value + ) + .toString + } + case NodeCreatePayloadADM.ChildNodeCreatePayloadADM( + _, + parentNodeIri, + projectIri, + name, + position, + labels, + comments + ) => { + org.knora.webapi.messages.twirl.queries.sparql.admin.txt + .createNewChildListNode( + dataNamedGraph = dataNamedGraph, + triplestore = settings.triplestoreType, + listClassIri = OntologyConstants.KnoraBase.ListNode, + projectIri = projectIri, + nodeIri = newListNodeIri, + parentNodeIri = parentNodeIri, + rootNodeIri = rootNodeIri, + position = position.map(_.value), + maybeName = name.map(_.value), + maybeLabels = labels.value, + maybeComments = comments.map(_.value) + ) + .toString + } + } _ <- (storeManager ? SparqlUpdateRequest(createNewListSparqlString)).mapTo[SparqlUpdateResponse] } yield newListNodeIri @@ -1149,7 +1190,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @return a [[ChildNodeInfoGetResponseADM]] */ private def listChildNodeCreateRequestADM( - createChildNodeRequest: NodeCreatePayloadADM, + createChildNodeRequest: ChildNodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[ChildNodeInfoGetResponseADM] = { @@ -1158,7 +1199,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * The actual task run with an IRI lock. */ def listChildNodeCreateTask( - createChildNodeRequest: NodeCreatePayloadADM, + createChildNodeRequest: ChildNodeCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, apiRequestID: UUID ): Future[ChildNodeInfoGetResponseADM] = @@ -1215,7 +1256,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde ): Future[NodeInfoGetResponseADM] = { def verifyUpdatedNode(updatedNode: ListNodeInfoADM): Unit = - if (updatedNode.getName.nonEmpty && updatedNode.getName.get != changeNodeNameRequest.name) + if (updatedNode.getName.nonEmpty && updatedNode.getName.get != changeNodeNameRequest.name.value) throw UpdateNotPerformedException("Node's 'name' was not updated. Please report this as a possible bug.") /** @@ -1385,7 +1426,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = { def verifyUpdatedNode(updatedNode: ListNodeInfoADM): Unit = - if (updatedNode.getComments.stringLiterals.diff(changeNodeCommentsRequest.comments.value).nonEmpty) + if (updatedNode.getComments.stringLiterals.diff(changeNodeCommentsRequest.comments.get.value).nonEmpty) throw UpdateNotPerformedException("Node's 'comments' were not updated. Please report this as a possible bug.") /** @@ -1412,7 +1453,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde changeNodeInfoRequest = NodeInfoChangePayloadADM( listIri = nodeIri, projectIri = projectIri, - comments = Some(changeNodeCommentsRequest.comments) + comments = changeNodeCommentsRequest.comments ), featureFactoryConfig = featureFactoryConfig ) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 18ab0a2cfe..6a2c4c2f67 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -26,8 +26,13 @@ import io.swagger.annotations._ import javax.ws.rs.Path import org.knora.webapi.IRI -import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} +import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.LIST_CREATE_PERMISSION_ERROR +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ + ChildNodeCreatePayloadADM, + RootNodeCreatePayloadADM +} import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} @@ -156,6 +161,16 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list item (root or child node) */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => + val id = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.id, + throw BadRequestException(s"Invalid custom node IRI") + ) + + val parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( + apiRequest.parentNodeIri, + throw BadRequestException(s"Invalid parent node IRI") + ) + val maybeName: Option[Name] = apiRequest.name match { case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) case None => None @@ -166,31 +181,51 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM( - id = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.id, - throw BadRequestException(s"Invalid custom node IRI") - ), - parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.parentNodeIri, - throw BadRequestException(s"Invalid parent node IRI") - ), - projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + val labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v) + val comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) + + val projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + + val createRootNodePayloadADM: RootNodeCreatePayloadADM = RootNodeCreatePayloadADM( + id, + parentNodeIri, + projectIri, + name = maybeName, + position = maybePosition, + labels, + comments + ) + + val createChildNodePayloadADM: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( + id, + parentNodeIri, + projectIri, name = maybeName, position = maybePosition, - labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), - comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) + labels, + comments = Some(comments) ) val requestMessage = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) + // check if the requesting user is allowed to perform operation + _ = println( + "77777", + requestingUser.permissions.isProjectAdmin(projectIri), + requestingUser.permissions.isSystemAdmin + ) + _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + // not project or a system admin + throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) + } + // Is parent node IRI given in the payload? createRequest = if (apiRequest.parentNodeIri.isEmpty) { // No, create a new list with given information of its root node. ListCreateRequestADM( - createRootNode = nodeCreatePayloadADM, + createRootNode = createRootNodePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -198,7 +233,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) } else { // Yes, create a new child and attach it to the parent node. ListChildNodeCreateRequestADM( - createChildNodeRequest = nodeCreatePayloadADM, + createChildNodeRequest = createChildNodePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -308,6 +343,9 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val listIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) + val projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + val maybeName: Option[Name] = apiRequest.name match { case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) case None => None @@ -330,8 +368,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, - projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + projectIri, hasRootNode = stringFormatter.validateAndEscapeOptionalIri( apiRequest.hasRootNode, throw BadRequestException(s"Invalid root node IRI") @@ -344,6 +381,11 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val requestMessage: Future[NodeInfoChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) + // check if the requesting user is allowed to perform operation + _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + // not project or a system admin + throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) + } } yield NodeInfoChangeRequestADM( //TODO: why "listIri" property is doubled - here and inside "changeNodeRequest" listIri = listIri, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index cb4ed01c85..c05df3797e 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -26,8 +26,16 @@ import io.swagger.annotations._ import javax.ws.rs.Path import org.knora.webapi.IRI -import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} +import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ + LIST_CREATE_PERMISSION_ERROR, + LIST_NODE_CREATE_PERMISSION_ERROR +} +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ + ChildNodeCreatePayloadADM, + RootNodeCreatePayloadADM +} import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} @@ -140,7 +148,10 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM( + val projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + + val createRootNodePayloadADM: RootNodeCreatePayloadADM = RootNodeCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( apiRequest.id, throw BadRequestException(s"Invalid custom node IRI") @@ -149,23 +160,28 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) apiRequest.parentNodeIri, throw BadRequestException(s"Invalid parent node IRI") ), - projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + projectIri, name = maybeName, position = maybePosition, labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) ) - println("XXXXX", nodeCreatePayloadADM) + println("XXXXX", createRootNodePayloadADM) val requestMessage: Future[ListCreateRequestADM] = for { requestingUser <- getUserADM( requestContext = requestContext, featureFactoryConfig = featureFactoryConfig ) + + // check if the requesting user is allowed to perform operation + _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + // not project or a system admin + throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) + } } yield ListCreateRequestADM( - createRootNode = nodeCreatePayloadADM, + createRootNode = createRootNodePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -273,10 +289,12 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } + val projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, - projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + projectIri, hasRootNode = stringFormatter.validateAndEscapeOptionalIri( apiRequest.hasRootNode, throw BadRequestException(s"Invalid root node IRI") @@ -289,6 +307,11 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val requestMessage: Future[NodeInfoChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) + // check if the requesting user is allowed to perform operation + _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + // not project or a system admin + throw ForbiddenException(LIST_NODE_CREATE_PERMISSION_ERROR) + } } yield NodeInfoChangeRequestADM( listIri = listIri, changeNodeRequest = changeNodeInfoPayloadADM, @@ -340,7 +363,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* add node to existing list node. the existing list node can be either the root or a child */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => -// val _ = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) + val projectIri = stringFormatter + .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) val maybeName: Option[Name] = apiRequest.name match { case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) @@ -352,7 +376,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val nodeCreatePayloadADM: NodeCreatePayloadADM = NodeCreatePayloadADM( + val createChildNodeRequest: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( apiRequest.id, throw BadRequestException(s"Invalid custom node IRI") @@ -361,12 +385,11 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) apiRequest.parentNodeIri, throw BadRequestException(s"Invalid parent node IRI") ), - projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")), + projectIri, name = maybeName, position = maybePosition, labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), - comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) + comments = Some(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) ) val requestMessage: Future[ListChildNodeCreateRequestADM] = for { @@ -374,8 +397,16 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) requestContext = requestContext, featureFactoryConfig = featureFactoryConfig ) + + // check if the requesting user is allowed to perform operation + _ = if ( + !requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin + ) { + // not project or a system admin + throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) + } } yield ListChildNodeCreateRequestADM( - createChildNodeRequest = nodeCreatePayloadADM, + createChildNodeRequest = createChildNodeRequest, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala index a8ffc53f8a..31d39bd1e5 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala @@ -204,13 +204,16 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) private def updateNodeComments(featureFactoryConfig: FeatureFactoryConfig): Route = path(ListsBasePath / Segment / "comments") { iri => put { - /* update labels of an existing list node (either root or child) */ + /* update comments of an existing list node (either root or child) */ entity(as[ChangeNodeCommentsApiRequestADM]) { apiRequest => requestContext => val nodeIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) - val commentsPayload: NodeCommentsChangePayloadADM = - NodeCommentsChangePayloadADM(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) + val commentsPayload: NodeCommentsChangePayloadADM = if (apiRequest.comments.isEmpty) { + NodeCommentsChangePayloadADM(None) + } else { + NodeCommentsChangePayloadADM(Some(Comments.create(apiRequest.comments).fold(e => throw e, v => v))) + } val requestMessage: Future[NodeCommentsChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt new file mode 100644 index 0000000000..f6d6f0546f --- /dev/null +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt @@ -0,0 +1,136 @@ +@* + * Copyright © 2015-2021 Data and Service Center for the Humanities (DaSCH) + * + * This file is part of Knora. + * + * Knora is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knora is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with Knora. If not, see . + *@ + +@import org.knora.webapi.IRI +@import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 + +@* +TODO: since root and child node have now separated sparql templates these could be improved +*@ + +@* + * Creates a new child list node. + * + * @param dataNamedGraph the name of the graph into which the new list node will be created. + * @param triplestore the name of the triplestore being used. The template uses this value to exclude inferred + results from the WHERE clause of the update. + * @param listClassIri the IRI of the OWL class that the list should belong to. + * @param projectIri the IRI of the list's project. + * @param nodeIri the IRI of the new list node. + * @param parentNodeIri the IRI of the parent node if creating a child node. + * @param rootNodeIri the IRI of the root node if creating a child node. + * @param position the position of the new node if creating a child node. + * @param maybeName the optional name of the node. + * @param maybeLabels the new node's labels. + * @param maybeComments the new node's comments. + * + *@ +@(dataNamedGraph: IRI, + triplestore: String, + listClassIri: IRI, + projectIri : IRI, + nodeIri: IRI, + parentNodeIri: Option[IRI], + rootNodeIri: Option[IRI], + position: Option[Int], + maybeName: Option[String], + maybeLabels: Seq[StringLiteralV2], + maybeComments: Option[Seq[StringLiteralV2]] +) + +PREFIX xsd: +PREFIX rdf: +PREFIX rdfs: +PREFIX owl: +PREFIX knora-base: +PREFIX foaf: + +INSERT { + GRAPH ?dataNamedGraph { + ?nodeIri rdf:type ?listClassIri . + + @if(parentNodeIri.nonEmpty) { + ?parentNodeIri knora-base:hasSubListNode ?nodeIri . + + ?nodeIri knora-base:hasRootNode ?rootNodeIri . + + ?nodeIri knora-base:listNodePosition "@position.get"^^xsd:integer . + } else { + ?nodeIri knora-base:attachedToProject ?projectIri . + + ?nodeIri knora-base:isRootNode "true"^^xsd:boolean . + + } + + @if(maybeName.nonEmpty) { + ?nodeIri knora-base:listNodeName "@maybeName.get"^^xsd:string . + } + + @if(maybeLabels.nonEmpty) { + @for(label <- maybeLabels) { + @if(label.language.nonEmpty) { + ?nodeIri rdfs:label """@label.value"""@@@{label.language.get} . + } else { + ?nodeIri rdfs:label """@label.value"""^^xsd:string . + } + } + } +@* + @if(maybeComments.nonEmpty) { + @for(comment <- maybeComments.get) { + @if(comment.language.nonEmpty) { + ?nodeIri rdfs:comment """@comment.value"""@@@{comment.language.get} . + } else { + ?nodeIri rdfs:comment """@comment.value"""^^xsd:string . + } + } + } +*@ + @if(maybeComments.nonEmpty) { + ?nodeIri rdfs:comment ?currentComments . + } + } +} +@* + +GraphDB's consistency checking requires reasoning, but reasoning interferes with certain things +in the WHERE clauses of our SPARQL updates, so we set a GraphDB-specific flag to return only +explicit statements in the WHERE clause here. + +*@ +@triplestore match { + case "graphdb" | "graphdb-free" => { + USING + } + + case other => {} +} +WHERE { + BIND(IRI("@dataNamedGraph") AS ?dataNamedGraph) + BIND(IRI("@nodeIri") AS ?nodeIri) + @if(parentNodeIri.nonEmpty) { + BIND(IRI("@parentNodeIri.get") AS ?parentNodeIri) + } + @if(rootNodeIri.nonEmpty) { + BIND(IRI("@rootNodeIri.get") AS ?rootNodeIri) + } + BIND(IRI("@listClassIri") AS ?listClassIri) + BIND(IRI("@projectIri") AS ?projectIri) + FILTER NOT EXISTS { ?nodeIri rdf:type ?listClassIri . } +} diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewRootListNode.scala.txt similarity index 95% rename from webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt rename to webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewRootListNode.scala.txt index 51908c6b06..7702b06213 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewRootListNode.scala.txt @@ -21,7 +21,11 @@ @import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 @* - * Creates a new list node. +TODO: since root and child node have now separated sparql templates these could be improved +*@ + +@* + * Creates a new root list node. * * @param dataNamedGraph the name of the graph into which the new list node will be created. * @param triplestore the name of the triplestore being used. The template uses this value to exclude inferred @@ -31,7 +35,7 @@ * @param nodeIri the IRI of the new list node. * @param parentNodeIri the IRI of the parent node if creating a child node. * @param rootNodeIri the IRI of the root node if creating a child node. - * @param position the position of the of the new node if creating a child node. + * @param position the position of the new node if creating a child node. * @param maybeName the optional name of the node. * @param maybeLabels the new node's labels. * @param maybeComments the new node's comments. diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala index 447523ab4d..24cac4174f 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala @@ -233,7 +233,7 @@ class UpdateListItemsRouteADME2ESpec HttpEntity(ContentTypes.`application/json`, deleteCommentsLabels) ) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) val response: HttpResponse = singleAwaitingRequest(request) - // log.debug(s"response: ${response.toString}") + log.debug(s"response: ${response.toString}") response.status should be(StatusCodes.OK) val receivedListInfo: ListRootNodeInfoADM = AkkaHttpUtils.httpResponseToJson(response).fields("listinfo").convertTo[ListRootNodeInfoADM] diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index 4fdc7ad9f7..1460eab344 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -24,6 +24,10 @@ import com.typesafe.config.ConfigFactory import org.knora.webapi.CoreSpec import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ + ChildNodeCreatePayloadADM, + RootNodeCreatePayloadADM +} import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} import org.knora.webapi.sharedtestdata.SharedTestDataV1.IMAGES_PROJECT_IRI @@ -146,12 +150,11 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'ForbiddenException' if user requesting `ListCreateApiRequestADM` is not system or project admin" in { val caught = intercept[ForbiddenException]( ListCreateRequestADM( - createRootNode = NodeCreatePayloadADM( + createRootNode = RootNodeCreatePayloadADM( projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, labels = Labels .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] comments = Comments .create(Seq(StringLiteralV2(value = "Neuer Kommentar", language = Some("de")))) .fold(e => throw e, v => v) @@ -364,16 +367,17 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'ForbiddenException' if user requesting `createChildNodeRequest` is not system or project admin" in { val caught = intercept[ForbiddenException]( ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM( + createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(exampleListIri), projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, labels = Labels .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) - .fold(e => throw e, v => v) + comments = Some( + Comments + .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) + .fold(e => throw e, v => v) + ) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser02, @@ -386,17 +390,18 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li "throw 'BadRequestException' if invalid position given in payload of `createChildNodeRequest`" in { val caught = intercept[BadRequestException]( ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM( + createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(exampleListIri), projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, position = Some(Position.create(-3).fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) - .fold(e => throw e, v => v) + comments = Some( + Comments + .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) + .fold(e => throw e, v => v) + ) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 054b8023f5..ef9853d877 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -20,19 +20,22 @@ package org.knora.webapi.responders.admin import java.util.UUID - import akka.actor.Status.Failure import akka.testkit._ import com.typesafe.config.{Config, ConfigFactory} import org.knora.webapi._ import org.knora.webapi.exceptions.{BadRequestException, DuplicateValueException, UpdateNotPerformedException} import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ + ChildNodeCreatePayloadADM, + RootNodeCreatePayloadADM +} import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, StringLiteralV2} import org.knora.webapi.sharedtestdata.SharedTestDataV1._ import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} import org.knora.webapi.util.MutableTestIri -import org.knora.webapi.messages.admin.responder.valueObjects.{Name, Comments, Labels, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import scala.concurrent.duration._ @@ -177,13 +180,12 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "used to modify lists" should { "create a list" in { responderManager ! ListCreateRequestADM( - createRootNode = NodeCreatePayloadADM( + createRootNode = RootNodeCreatePayloadADM( projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("neuelistename").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] comments = Comments .create(Seq(StringLiteralV2(value = "Neuer Kommentar", language = Some("de")))) .fold(e => throw e, v => v) @@ -219,13 +221,12 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val commentWithSpecialCharacter = "Neue \\\"Kommentar\\\"" val nameWithSpecialCharacter = "a new \\\"name\\\"" responderManager ! ListCreateRequestADM( - createRootNode = NodeCreatePayloadADM( + createRootNode = RootNodeCreatePayloadADM( projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = labelWithSpecialCharacter, language = Some("de")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] comments = Comments .create(Seq(StringLiteralV2(value = commentWithSpecialCharacter, language = Some("de")))) .fold(e => throw e, v => v) @@ -339,17 +340,18 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to list - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM( + createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("first").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) + comments = Some( + Comments + .create(Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -390,7 +392,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add second child to list in first position - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM( + createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("second").fold(e => throw e, v => v)), @@ -398,10 +400,11 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels = Labels .create(Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) + comments = Some( + Comments + .create(Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -442,17 +445,18 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to second child node" in { responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM( + createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(secondChildIri.get), projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("third").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) + comments = Some( + Comments + .create(Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -494,7 +498,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "not create a node if given new position is out of range" in { val givenPosition = Some(Position.create(20).fold(e => throw e, v => v)) responderManager ! ListChildNodeCreateRequestADM( - createChildNodeRequest = NodeCreatePayloadADM( + createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), projectIri = IMAGES_PROJECT_IRI, name = Some(Name.create("fourth").fold(e => throw e, v => v)), @@ -502,10 +506,11 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels = Labels .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Value", language = Some("en")))) .fold(e => throw e, v => v), - // TODO: remove/change if comments become optional for child nodes Seq.empty[StringLiteralV2] - comments = Comments - .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Comment", language = Some("en")))) - .fold(e => throw e, v => v) + comments = Some( + Comments + .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Comment", language = Some("en")))) + .fold(e => throw e, v => v) + ) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, From 812683f3d6c6a596675b96a6eb8fbfbf1bf941e6 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 18 Oct 2021 14:27:05 +0200 Subject: [PATCH 11/32] WIP: fix tests --- .../listsmessages/ListsMessagesADM.scala | 34 ++--- .../listsmessages/ListsMessagesV2.scala | 4 +- .../responders/admin/ListsResponderADM.scala | 16 +-- .../admin/createNewChildListNode.scala.txt | 136 ------------------ ....scala.txt => createNewListNode.scala.txt} | 18 ++- .../NewListsRoutesADMFeatureE2ESpec.scala | 6 +- .../OldListsRouteADMFeatureE2ESpec.scala | 8 +- .../UpdateListItemsRouteADME2ESpec.scala | 3 +- .../listsmessages/ListsMessagesADMSpec.scala | 82 +---------- .../admin/ListsResponderADMSpec.scala | 8 +- .../v2/ListsResponderV2SpecFullData.scala | 2 +- .../SharedListsTestDataADM.scala | 18 +-- 12 files changed, 61 insertions(+), 274 deletions(-) delete mode 100644 webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt rename webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/{createNewRootListNode.scala.txt => createNewListNode.scala.txt} (90%) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 10095b4f7c..6137c66355 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -694,10 +694,10 @@ case class ListChildNodeInfoADM( id: IRI, name: Option[String], labels: StringLiteralSequenceV2, - comments: StringLiteralSequenceV2, + comments: Option[StringLiteralSequenceV2], position: Int, hasRootNode: IRI -) extends ListNodeInfoADM(id, name, labels, comments) { +) extends ListNodeInfoADM(id, name, labels, comments.get) { /** * Sorts the whole hierarchy. @@ -709,7 +709,7 @@ case class ListChildNodeInfoADM( id = id, name = name, labels = labels.sortByStringValue, - comments = comments.sortByStringValue, + comments = comments.map(_.sortByStringValue), position = position, hasRootNode = hasRootNode ) @@ -722,14 +722,14 @@ case class ListChildNodeInfoADM( val unescapedLabels = stringFormatter.unescapeStringLiteralSeq(labels) - val unescapedComments = stringFormatter.unescapeStringLiteralSeq(comments) + val unescapedComments = stringFormatter.unescapeStringLiteralSeq(comments.get) val unescapedName: Option[String] = name match { case None => None case Some(value) => Some(stringFormatter.fromSparqlEncodedString(value)) } - copy(name = unescapedName, labels = unescapedLabels, comments = unescapedComments) + copy(name = unescapedName, labels = unescapedLabels, comments = Some(unescapedComments)) } /** @@ -750,7 +750,7 @@ case class ListChildNodeInfoADM( * @return the comment in the preferred language. */ def getCommentInPreferredLanguage(userLang: String, fallbackLang: String): Option[String] = - comments.getPreferredLanguage(userLang, fallbackLang) + comments.get.getPreferredLanguage(userLang, fallbackLang) } /** @@ -893,11 +893,11 @@ case class ListChildNodeADM( id: IRI, name: Option[String], labels: StringLiteralSequenceV2, - comments: StringLiteralSequenceV2, + comments: Option[StringLiteralSequenceV2], position: Int, hasRootNode: IRI, children: Seq[ListChildNodeADM] -) extends ListNodeADM(id, name, labels, comments, children) { +) extends ListNodeADM(id, name, labels, comments.get, children) { /** * Sorts the whole hierarchy. @@ -909,7 +909,7 @@ case class ListChildNodeADM( id = id, name = name, labels = labels.sortByStringValue, - comments = comments.sortByStringValue, + comments = comments.map(_.sortByStringValue), position = position, hasRootNode = hasRootNode, children = children.sortBy(_.position).map(_.sorted) @@ -922,14 +922,14 @@ case class ListChildNodeADM( val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance val unescapedLabels = stringFormatter.unescapeStringLiteralSeq(labels) - val unescapedComments = stringFormatter.unescapeStringLiteralSeq(comments) + val unescapedComments = stringFormatter.unescapeStringLiteralSeq(comments.get) val unescapedName: Option[String] = name match { case None => None case Some(value) => Some(stringFormatter.fromSparqlEncodedString(value)) } - copy(name = unescapedName, labels = unescapedLabels, comments = unescapedComments) + copy(name = unescapedName, labels = unescapedLabels, comments = Some(unescapedComments)) } /** @@ -950,7 +950,7 @@ case class ListChildNodeADM( * @return the comment in the preferred language. */ def getCommentInPreferredLanguage(userLang: String, fallbackLang: String): Option[String] = - comments.getPreferredLanguage(userLang, fallbackLang) + comments.get.getPreferredLanguage(userLang, fallbackLang) } /** @@ -1032,7 +1032,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with "id" -> child.id.toJson, "name" -> child.name.toJson, "labels" -> JsArray(child.labels.stringLiterals.map(_.toJson)), - "comments" -> JsArray(child.comments.stringLiterals.map(_.toJson)), + "comments" -> JsArray(child.comments.get.stringLiterals.map(_.toJson)), "position" -> child.position.toJson, "hasRootNode" -> child.hasRootNode.toJson ) @@ -1040,7 +1040,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with JsObject( "id" -> child.id.toJson, "labels" -> JsArray(child.labels.stringLiterals.map(_.toJson)), - "comments" -> JsArray(child.comments.stringLiterals.map(_.toJson)), + "comments" -> JsArray(child.comments.get.stringLiterals.map(_.toJson)), "position" -> child.position.toJson, "hasRootNode" -> child.hasRootNode.toJson ) @@ -1098,7 +1098,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with id = id, name = name, labels = StringLiteralSequenceV2(labels.toVector), - comments = StringLiteralSequenceV2(comments.toVector), + comments = Some(StringLiteralSequenceV2(comments.toVector)), position = maybePosition.getOrElse(throw DeserializationException("The position is not defined.")), hasRootNode = maybeHasRootNode.getOrElse(throw DeserializationException("The root node is not defined.")) ) @@ -1152,7 +1152,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with "id" -> child.id.toJson, "name" -> child.name.toJson, "labels" -> JsArray(child.labels.stringLiterals.map(_.toJson)), - "comments" -> JsArray(child.comments.stringLiterals.map(_.toJson)), + "comments" -> JsArray(child.comments.get.stringLiterals.map(_.toJson)), "position" -> child.position.toJson, "hasRootNode" -> child.hasRootNode.toJson, "children" -> JsArray(child.children.map(write).toVector) @@ -1217,7 +1217,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with id = id, name = name, labels = StringLiteralSequenceV2(labels.toVector), - comments = StringLiteralSequenceV2(comments.toVector), + comments = Some(StringLiteralSequenceV2(comments.toVector)), position = maybePosition.getOrElse(throw DeserializationException("The position is not defined.")), hasRootNode = maybeHasRootNode.getOrElse(throw DeserializationException("The root node is not defined.")), children = children diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala index e74d3d7f10..014607ca45 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala @@ -104,7 +104,7 @@ case class ListGetResponseV2(list: ListADM, userLang: String, fallbackLang: Stri val label: Map[IRI, JsonLDString] = makeMapIriToJSONLDString(OntologyConstants.Rdfs.Label, node.labels, userLang, fallbackLang) val comment: Map[IRI, JsonLDString] = - makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, node.comments, userLang, fallbackLang) + makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, node.comments.get, userLang, fallbackLang) val position: Map[IRI, JsonLDInt] = Map( OntologyConstants.KnoraBase.ListNodePosition.toSmartIri.toOntologySchema(ApiV2Complex).toString -> JsonLDInt( @@ -249,7 +249,7 @@ case class NodeGetResponseV2(node: ListNodeInfoADM, userLang: String, fallbackLa makeMapIriToJSONLDString(OntologyConstants.Rdfs.Label, child.labels, userLang, fallbackLang) val comment: Map[IRI, JsonLDString] = - makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, child.comments, userLang, fallbackLang) + makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, child.comments.get, userLang, fallbackLang) val position: Map[IRI, JsonLDInt] = Map( OntologyConstants.KnoraBase.ListNodePosition.toSmartIri.toOntologySchema(ApiV2Complex).toString -> JsonLDInt( diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index e1e59e772d..6f08a6f242 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -424,7 +424,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde .get(OntologyConstants.KnoraBase.ListNodeName.toSmartIri) .map(_.head.asInstanceOf[StringLiteralV2].value), labels = StringLiteralSequenceV2(labels.toVector.sortBy(_.language)), - comments = StringLiteralSequenceV2(comments.toVector.sortBy(_.language)), + comments = Some(StringLiteralSequenceV2(comments.toVector.sortBy(_.language))), position = positionOption.getOrElse( throw InconsistentRepositoryDataException( s"Required position property missing for list node $nodeIri." @@ -603,7 +603,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde .get(OntologyConstants.KnoraBase.ListNodeName.toSmartIri) .map(_.head.asInstanceOf[StringLiteralV2].value), labels = StringLiteralSequenceV2(labels.toVector.sortBy(_.language)), - comments = StringLiteralSequenceV2(comments.toVector.sortBy(_.language)), + comments = Some(StringLiteralSequenceV2(comments.toVector.sortBy(_.language))), position = positionOption.getOrElse( throw InconsistentRepositoryDataException( s"Required position property missing for list node $nodeIri." @@ -702,7 +702,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde id = nodeIri, name = nameOption, labels = StringLiteralSequenceV2(labels.toVector.sortBy(_.language)), - comments = StringLiteralSequenceV2(comments.toVector.sortBy(_.language)), + comments = Some(StringLiteralSequenceV2(comments.toVector.sortBy(_.language))), children = children.map(_.sorted), position = position, hasRootNode = hasRootNode @@ -964,7 +964,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde dataNamedGraph: IRI = stringFormatter.projectDataNamedGraphV2(project) // if parent node is known, find the root node of the list and the position of the new child node - (position: Option[Int], rootNodeIri: Option[IRI]) <- + (newPosition: Option[Int], rootNodeIri: Option[IRI]) <- if (parentNodeIri.nonEmpty) { getRootNodeAndPositionOfNewChild( parentNodeIri = parentNodeIri.get, @@ -992,7 +992,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde comments ) => { org.knora.webapi.messages.twirl.queries.sparql.admin.txt - .createNewRootListNode( + .createNewListNode( dataNamedGraph = dataNamedGraph, triplestore = settings.triplestoreType, listClassIri = OntologyConstants.KnoraBase.ListNode, @@ -1003,7 +1003,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde position = position.map(_.value), maybeName = name.map(_.value), maybeLabels = labels.value, - maybeComments = comments.value + maybeComments = Some(comments.value) ) .toString } @@ -1017,7 +1017,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde comments ) => { org.knora.webapi.messages.twirl.queries.sparql.admin.txt - .createNewChildListNode( + .createNewListNode( dataNamedGraph = dataNamedGraph, triplestore = settings.triplestoreType, listClassIri = OntologyConstants.KnoraBase.ListNode, @@ -1025,7 +1025,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde nodeIri = newListNodeIri, parentNodeIri = parentNodeIri, rootNodeIri = rootNodeIri, - position = position.map(_.value), + position = newPosition, maybeName = name.map(_.value), maybeLabels = labels.value, maybeComments = comments.map(_.value) diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt deleted file mode 100644 index f6d6f0546f..0000000000 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewChildListNode.scala.txt +++ /dev/null @@ -1,136 +0,0 @@ -@* - * Copyright © 2015-2021 Data and Service Center for the Humanities (DaSCH) - * - * This file is part of Knora. - * - * Knora is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knora is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public - * License along with Knora. If not, see . - *@ - -@import org.knora.webapi.IRI -@import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 - -@* -TODO: since root and child node have now separated sparql templates these could be improved -*@ - -@* - * Creates a new child list node. - * - * @param dataNamedGraph the name of the graph into which the new list node will be created. - * @param triplestore the name of the triplestore being used. The template uses this value to exclude inferred - results from the WHERE clause of the update. - * @param listClassIri the IRI of the OWL class that the list should belong to. - * @param projectIri the IRI of the list's project. - * @param nodeIri the IRI of the new list node. - * @param parentNodeIri the IRI of the parent node if creating a child node. - * @param rootNodeIri the IRI of the root node if creating a child node. - * @param position the position of the new node if creating a child node. - * @param maybeName the optional name of the node. - * @param maybeLabels the new node's labels. - * @param maybeComments the new node's comments. - * - *@ -@(dataNamedGraph: IRI, - triplestore: String, - listClassIri: IRI, - projectIri : IRI, - nodeIri: IRI, - parentNodeIri: Option[IRI], - rootNodeIri: Option[IRI], - position: Option[Int], - maybeName: Option[String], - maybeLabels: Seq[StringLiteralV2], - maybeComments: Option[Seq[StringLiteralV2]] -) - -PREFIX xsd: -PREFIX rdf: -PREFIX rdfs: -PREFIX owl: -PREFIX knora-base: -PREFIX foaf: - -INSERT { - GRAPH ?dataNamedGraph { - ?nodeIri rdf:type ?listClassIri . - - @if(parentNodeIri.nonEmpty) { - ?parentNodeIri knora-base:hasSubListNode ?nodeIri . - - ?nodeIri knora-base:hasRootNode ?rootNodeIri . - - ?nodeIri knora-base:listNodePosition "@position.get"^^xsd:integer . - } else { - ?nodeIri knora-base:attachedToProject ?projectIri . - - ?nodeIri knora-base:isRootNode "true"^^xsd:boolean . - - } - - @if(maybeName.nonEmpty) { - ?nodeIri knora-base:listNodeName "@maybeName.get"^^xsd:string . - } - - @if(maybeLabels.nonEmpty) { - @for(label <- maybeLabels) { - @if(label.language.nonEmpty) { - ?nodeIri rdfs:label """@label.value"""@@@{label.language.get} . - } else { - ?nodeIri rdfs:label """@label.value"""^^xsd:string . - } - } - } -@* - @if(maybeComments.nonEmpty) { - @for(comment <- maybeComments.get) { - @if(comment.language.nonEmpty) { - ?nodeIri rdfs:comment """@comment.value"""@@@{comment.language.get} . - } else { - ?nodeIri rdfs:comment """@comment.value"""^^xsd:string . - } - } - } -*@ - @if(maybeComments.nonEmpty) { - ?nodeIri rdfs:comment ?currentComments . - } - } -} -@* - -GraphDB's consistency checking requires reasoning, but reasoning interferes with certain things -in the WHERE clauses of our SPARQL updates, so we set a GraphDB-specific flag to return only -explicit statements in the WHERE clause here. - -*@ -@triplestore match { - case "graphdb" | "graphdb-free" => { - USING - } - - case other => {} -} -WHERE { - BIND(IRI("@dataNamedGraph") AS ?dataNamedGraph) - BIND(IRI("@nodeIri") AS ?nodeIri) - @if(parentNodeIri.nonEmpty) { - BIND(IRI("@parentNodeIri.get") AS ?parentNodeIri) - } - @if(rootNodeIri.nonEmpty) { - BIND(IRI("@rootNodeIri.get") AS ?rootNodeIri) - } - BIND(IRI("@listClassIri") AS ?listClassIri) - BIND(IRI("@projectIri") AS ?projectIri) - FILTER NOT EXISTS { ?nodeIri rdf:type ?listClassIri . } -} diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewRootListNode.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt similarity index 90% rename from webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewRootListNode.scala.txt rename to webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt index 7702b06213..4ea96c9abe 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewRootListNode.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewListNode.scala.txt @@ -20,10 +20,6 @@ @import org.knora.webapi.IRI @import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -@* -TODO: since root and child node have now separated sparql templates these could be improved -*@ - @* * Creates a new root list node. * @@ -51,7 +47,7 @@ TODO: since root and child node have now separated sparql templates these could position: Option[Int], maybeName: Option[String], maybeLabels: Seq[StringLiteralV2], - maybeComments: Seq[StringLiteralV2] + maybeComments: Option[Seq[StringLiteralV2]] ) PREFIX xsd: @@ -93,11 +89,13 @@ INSERT { } @if(maybeComments.nonEmpty) { - @for(comment <- maybeComments) { - @if(comment.language.nonEmpty) { - ?nodeIri rdfs:comment """@comment.value"""@@@{comment.language.get} . - } else { - ?nodeIri rdfs:comment """@comment.value"""^^xsd:string . + @if(maybeComments.get.nonEmpty) { + @for(comment <- maybeComments.get) { + @if(comment.language.nonEmpty) { + ?nodeIri rdfs:comment """@comment.value"""@@@{comment.language.get} . + } else { + ?nodeIri rdfs:comment """@comment.value"""^^xsd:string . + } } } } diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala index 3d4107c71f..ecb0da46df 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala @@ -875,7 +875,7 @@ class NewListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -945,7 +945,7 @@ class NewListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -1017,7 +1017,7 @@ class NewListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala index a007bf0bde..88de15e509 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala @@ -847,7 +847,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -918,7 +918,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -995,7 +995,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -1068,7 +1068,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala index 24cac4174f..9f6fd4f822 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala @@ -222,6 +222,7 @@ class UpdateListItemsRouteADME2ESpec ) } "delete node comments" in { + val deleteCommentsLabels = s"""{ | "comments": [] @@ -364,7 +365,7 @@ class UpdateListItemsRouteADME2ESpec val receivedNodeInfo: ListChildNodeInfoADM = AkkaHttpUtils.httpResponseToJson(response).fields("nodeinfo").convertTo[ListChildNodeInfoADM] - val comments: Seq[StringLiteralV2] = receivedNodeInfo.comments.stringLiterals + val comments: Seq[StringLiteralV2] = receivedNodeInfo.comments.get.stringLiterals comments.size should be(1) comments should contain(StringLiteralV2(value = "nya kommentarer för nod", language = Some("se"))) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index 1460eab344..ff9c59afd0 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -82,7 +82,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li id = "http://rdfh.ch/lists/00FF/526f26ed04", name = Some("sommer"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2("Sommer"))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), position = 0, hasRootNode = "http://rdfh.ch/lists/00FF/d19af9ab" ) @@ -102,7 +102,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li id = "http://rdfh.ch/lists/00FF/526f26ed04", name = Some("sommer"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2("Sommer"))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq.empty[ListChildNodeADM], position = 0, hasRootNode = "http://rdfh.ch/lists/00FF/d19af9ab" @@ -147,26 +147,6 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li converted.children should be(children) } - "throw 'ForbiddenException' if user requesting `ListCreateApiRequestADM` is not system or project admin" in { - val caught = intercept[ForbiddenException]( - ListCreateRequestADM( - createRootNode = RootNodeCreatePayloadADM( - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - labels = Labels - .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) - .fold(e => throw e, v => v), - comments = Comments - .create(Seq(StringLiteralV2(value = "Neuer Kommentar", language = Some("de")))) - .fold(e => throw e, v => v) - ), - featureFactoryConfig = defaultFeatureFactoryConfig, - requestingUser = SharedTestDataADM.imagesUser02, - apiRequestID = UUID.randomUUID() - ) - ) - assert(caught.getMessage === LIST_CREATE_PERMISSION_ERROR) - } - "throw 'BadRequestException' for `CreateListApiRequestADM` when project IRI is empty" in { val payload = @@ -364,28 +344,6 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li thrown.getMessage should equal(INVALID_POSITION) } - "throw 'ForbiddenException' if user requesting `createChildNodeRequest` is not system or project admin" in { - val caught = intercept[ForbiddenException]( - ListChildNodeCreateRequestADM( - createChildNodeRequest = ChildNodeCreatePayloadADM( - parentNodeIri = Some(exampleListIri), - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, - labels = Labels - .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) - .fold(e => throw e, v => v), - comments = Some( - Comments - .create(Seq(StringLiteralV2(value = "New child comment", language = Some("en")))) - .fold(e => throw e, v => v) - ) - ), - featureFactoryConfig = defaultFeatureFactoryConfig, - requestingUser = SharedTestDataADM.imagesUser02, - apiRequestID = UUID.randomUUID() - ) - ) - assert(caught.getMessage === LIST_NODE_CREATE_PERMISSION_ERROR) - } "throw 'BadRequestException' if invalid position given in payload of `createChildNodeRequest`" in { val caught = intercept[BadRequestException]( @@ -411,42 +369,6 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li assert(caught.getMessage === INVALID_POSITION) } - "return a 'ForbiddenException' if the user changing the node info is not project or system admin" in { - val caught = intercept[ForbiddenException]( - NodeInfoChangeRequestADM( - listIri = exampleListIri, - changeNodeRequest = NodeInfoChangePayloadADM( - listIri = exampleListIri, - projectIri = IMAGES_PROJECT_IRI, - labels = Some( - Labels - .create( - Seq( - StringLiteralV2(value = "Neue geänderte Liste", language = Some("de")), - StringLiteralV2(value = "Changed List", language = Some("en")) - ) - ) - .fold(e => throw e, v => v) - ), - comments = Some( - Comments - .create( - Seq( - StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), - StringLiteralV2(value = "New Comment", language = Some("en")) - ) - ) - .fold(e => throw e, v => v) - ) - ), - featureFactoryConfig = defaultFeatureFactoryConfig, - requestingUser = SharedTestDataADM.imagesUser02, - apiRequestID = UUID.randomUUID - ) - ) - assert(caught.getMessage === LIST_CHANGE_PERMISSION_ERROR) - } - "throw 'BadRequestException' for `createChildNodeRequest` when no parent node iri is given" in { val payload = diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index ef9853d877..81cf7759eb 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -358,6 +358,8 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with apiRequestID = UUID.randomUUID ) + // log.debug(s"response: ${response.toString}") + val received: ChildNodeInfoGetResponseADM = expectMsgType[ChildNodeInfoGetResponseADM](timeout) val nodeInfo = received.nodeinfo @@ -373,7 +375,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.sorted should be(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be( Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en"))) @@ -426,7 +428,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.sorted should be(Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be( Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en"))) @@ -478,7 +480,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.sorted should be(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) // check comments - val comments = childNodeInfo.comments.stringLiterals + val comments = childNodeInfo.comments.get.stringLiterals comments.size should be(1) comments.sorted should be( Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en"))) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala index 68b6f97c0e..13aba2aa02 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala @@ -32,7 +32,7 @@ class ListsResponderV2SpecFullData(implicit stringFormatter: StringFormatter) { ), position = 1, hasRootNode = "http://rdfh.ch/lists/0001/treeList", - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])) ), userLang = "de", fallbackLang = "en" diff --git a/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala b/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala index 93284800ca..a6658e61d7 100644 --- a/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala +++ b/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala @@ -22,7 +22,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/00FF/526f26ed04", name = Some("sommer"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2("Sommer"))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), position = 0, hasRootNode = "http://rdfh.ch/lists/00FF/d19af9ab" ) @@ -32,7 +32,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/00FF/526f26ed04", name = Some("sommer"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2("Sommer"))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq.empty[ListChildNodeADM], position = 0, hasRootNode = "http://rdfh.ch/lists/00FF/d19af9ab" @@ -41,7 +41,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/00FF/eda2792605", name = Some("winter"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2("Winter"))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq.empty[ListChildNodeADM], position = 1, hasRootNode = "http://rdfh.ch/lists/00FF/d19af9ab" @@ -86,7 +86,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/0001/treeList01", name = Some("Tree list node 01"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2(value = "Tree list node 01", language = Some("en")))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), position = 0, hasRootNode = "http://rdfh.ch/lists/0001/treeList" ) @@ -95,7 +95,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/0001/treeList01", name = Some("Tree list node 01"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2(value = "Tree list node 01", language = Some("en")))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq.empty[ListChildNodeADM], position = 0, hasRootNode = "http://rdfh.ch/lists/0001/treeList" @@ -109,7 +109,7 @@ object SharedListsTestDataADM { StringLiteralV2(value = "Tree list node 02", language = Some("en")) ) ), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq.empty[ListChildNodeADM], position = 1, hasRootNode = "http://rdfh.ch/lists/0001/treeList" @@ -118,13 +118,13 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/0001/treeList03", name = Some("Tree list node 03"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2(value = "Tree list node 03", language = Some("en")))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq( ListChildNodeADM( id = "http://rdfh.ch/lists/0001/treeList10", name = Some("Tree list node 10"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2(value = "Tree list node 10", language = Some("en")))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq.empty[ListChildNodeADM], position = 0, hasRootNode = "http://rdfh.ch/lists/0001/treeList" @@ -133,7 +133,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/0001/treeList11", name = Some("Tree list node 11"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2(value = "Tree list node 11", language = Some("en")))), - comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), + comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children = Seq.empty[ListChildNodeADM], position = 1, hasRootNode = "http://rdfh.ch/lists/0001/treeList" From d2745d118ff68bcd1bd139606561aec6803518ee Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 20 Oct 2021 09:44:48 +0200 Subject: [PATCH 12/32] bring back ListChildNodeInfoADM non-optional comments --- .../listsmessages/ListPayloadsADM.scala | 2 +- .../listsmessages/ListsMessagesADM.scala | 18 +++++++++--------- .../listsmessages/ListsMessagesV2.scala | 2 +- .../responders/admin/ListsResponderADM.scala | 2 +- .../NewListsRoutesADMFeatureE2ESpec.scala | 6 +++--- .../lists/OldListsRouteADMFeatureE2ESpec.scala | 8 ++++---- .../lists/UpdateListItemsRouteADME2ESpec.scala | 5 ++++- .../listsmessages/ListsMessagesADMSpec.scala | 2 +- .../admin/ListsResponderADMSpec.scala | 6 +++--- .../v2/ListsResponderV2SpecFullData.scala | 2 +- .../SharedListsTestDataADM.scala | 4 ++-- 11 files changed, 30 insertions(+), 27 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index 862368bf41..22cf8111a2 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -59,5 +59,5 @@ final case class NodeLabelsChangePayloadADM( * Node Comments update payload */ final case class NodeCommentsChangePayloadADM( - comments: Option[Comments] + comments: Option[Comments] = None ) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 6137c66355..dece6a6c5e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -694,10 +694,10 @@ case class ListChildNodeInfoADM( id: IRI, name: Option[String], labels: StringLiteralSequenceV2, - comments: Option[StringLiteralSequenceV2], + comments: StringLiteralSequenceV2, position: Int, hasRootNode: IRI -) extends ListNodeInfoADM(id, name, labels, comments.get) { +) extends ListNodeInfoADM(id, name, labels, comments) { /** * Sorts the whole hierarchy. @@ -709,7 +709,7 @@ case class ListChildNodeInfoADM( id = id, name = name, labels = labels.sortByStringValue, - comments = comments.map(_.sortByStringValue), + comments = comments, position = position, hasRootNode = hasRootNode ) @@ -722,14 +722,14 @@ case class ListChildNodeInfoADM( val unescapedLabels = stringFormatter.unescapeStringLiteralSeq(labels) - val unescapedComments = stringFormatter.unescapeStringLiteralSeq(comments.get) + val unescapedComments = stringFormatter.unescapeStringLiteralSeq(comments) val unescapedName: Option[String] = name match { case None => None case Some(value) => Some(stringFormatter.fromSparqlEncodedString(value)) } - copy(name = unescapedName, labels = unescapedLabels, comments = Some(unescapedComments)) + copy(name = unescapedName, labels = unescapedLabels, comments = unescapedComments) } /** @@ -750,7 +750,7 @@ case class ListChildNodeInfoADM( * @return the comment in the preferred language. */ def getCommentInPreferredLanguage(userLang: String, fallbackLang: String): Option[String] = - comments.get.getPreferredLanguage(userLang, fallbackLang) + comments.getPreferredLanguage(userLang, fallbackLang) } /** @@ -1032,7 +1032,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with "id" -> child.id.toJson, "name" -> child.name.toJson, "labels" -> JsArray(child.labels.stringLiterals.map(_.toJson)), - "comments" -> JsArray(child.comments.get.stringLiterals.map(_.toJson)), + "comments" -> JsArray(child.comments.stringLiterals.map(_.toJson)), "position" -> child.position.toJson, "hasRootNode" -> child.hasRootNode.toJson ) @@ -1040,7 +1040,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with JsObject( "id" -> child.id.toJson, "labels" -> JsArray(child.labels.stringLiterals.map(_.toJson)), - "comments" -> JsArray(child.comments.get.stringLiterals.map(_.toJson)), + "comments" -> JsArray(child.comments.stringLiterals.map(_.toJson)), "position" -> child.position.toJson, "hasRootNode" -> child.hasRootNode.toJson ) @@ -1098,7 +1098,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with id = id, name = name, labels = StringLiteralSequenceV2(labels.toVector), - comments = Some(StringLiteralSequenceV2(comments.toVector)), + comments = StringLiteralSequenceV2(comments.toVector), position = maybePosition.getOrElse(throw DeserializationException("The position is not defined.")), hasRootNode = maybeHasRootNode.getOrElse(throw DeserializationException("The root node is not defined.")) ) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala index 014607ca45..f49557dc03 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala @@ -249,7 +249,7 @@ case class NodeGetResponseV2(node: ListNodeInfoADM, userLang: String, fallbackLa makeMapIriToJSONLDString(OntologyConstants.Rdfs.Label, child.labels, userLang, fallbackLang) val comment: Map[IRI, JsonLDString] = - makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, child.comments.get, userLang, fallbackLang) + makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, child.comments, userLang, fallbackLang) val position: Map[IRI, JsonLDInt] = Map( OntologyConstants.KnoraBase.ListNodePosition.toSmartIri.toOntologySchema(ApiV2Complex).toString -> JsonLDInt( diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 6f08a6f242..276f86a6cd 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -424,7 +424,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde .get(OntologyConstants.KnoraBase.ListNodeName.toSmartIri) .map(_.head.asInstanceOf[StringLiteralV2].value), labels = StringLiteralSequenceV2(labels.toVector.sortBy(_.language)), - comments = Some(StringLiteralSequenceV2(comments.toVector.sortBy(_.language))), + comments = StringLiteralSequenceV2(comments.toVector.sortBy(_.language)), position = positionOption.getOrElse( throw InconsistentRepositoryDataException( s"Required position property missing for list node $nodeIri." diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala index ecb0da46df..3d4107c71f 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/NewListsRoutesADMFeatureE2ESpec.scala @@ -875,7 +875,7 @@ class NewListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -945,7 +945,7 @@ class NewListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -1017,7 +1017,7 @@ class NewListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala index 88de15e509..a007bf0bde 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala @@ -847,7 +847,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -918,7 +918,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -995,7 +995,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) @@ -1068,7 +1068,7 @@ class OldListsRouteADMFeatureE2ESpec labels.sorted should be(Seq(StringLiteralV2(value = label, language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be(Seq(StringLiteralV2(value = comment, language = Some("en")))) diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala index 9f6fd4f822..4cc389ed28 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala @@ -222,6 +222,8 @@ class UpdateListItemsRouteADME2ESpec ) } "delete node comments" in { +// this should fail because in root nodes comments are required - change on line 240 +// add another test which allow delete comments for child node val deleteCommentsLabels = s"""{ @@ -236,6 +238,7 @@ class UpdateListItemsRouteADME2ESpec val response: HttpResponse = singleAwaitingRequest(request) log.debug(s"response: ${response.toString}") response.status should be(StatusCodes.OK) +// response.status should be(StatusCodes.BadRequest) val receivedListInfo: ListRootNodeInfoADM = AkkaHttpUtils.httpResponseToJson(response).fields("listinfo").convertTo[ListRootNodeInfoADM] @@ -365,7 +368,7 @@ class UpdateListItemsRouteADME2ESpec val receivedNodeInfo: ListChildNodeInfoADM = AkkaHttpUtils.httpResponseToJson(response).fields("nodeinfo").convertTo[ListChildNodeInfoADM] - val comments: Seq[StringLiteralV2] = receivedNodeInfo.comments.get.stringLiterals + val comments: Seq[StringLiteralV2] = receivedNodeInfo.comments.stringLiterals comments.size should be(1) comments should contain(StringLiteralV2(value = "nya kommentarer för nod", language = Some("se"))) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index ff9c59afd0..e04f55c0b3 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -82,7 +82,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li id = "http://rdfh.ch/lists/00FF/526f26ed04", name = Some("sommer"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2("Sommer"))), - comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), + comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), position = 0, hasRootNode = "http://rdfh.ch/lists/00FF/d19af9ab" ) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 81cf7759eb..d7f9821591 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -375,7 +375,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.sorted should be(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be( Seq(StringLiteralV2(value = "New First Child List Node Comment", language = Some("en"))) @@ -428,7 +428,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.sorted should be(Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be( Seq(StringLiteralV2(value = "New Second Child List Node Comment", language = Some("en"))) @@ -480,7 +480,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with labels.sorted should be(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) // check comments - val comments = childNodeInfo.comments.get.stringLiterals + val comments = childNodeInfo.comments.stringLiterals comments.size should be(1) comments.sorted should be( Seq(StringLiteralV2(value = "New Third Child List Node Comment", language = Some("en"))) diff --git a/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala b/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala index 13aba2aa02..68b6f97c0e 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/v2/ListsResponderV2SpecFullData.scala @@ -32,7 +32,7 @@ class ListsResponderV2SpecFullData(implicit stringFormatter: StringFormatter) { ), position = 1, hasRootNode = "http://rdfh.ch/lists/0001/treeList", - comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])) + comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) ), userLang = "de", fallbackLang = "en" diff --git a/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala b/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala index a6658e61d7..6433bab674 100644 --- a/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala +++ b/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedListsTestDataADM.scala @@ -22,7 +22,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/00FF/526f26ed04", name = Some("sommer"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2("Sommer"))), - comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), + comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), position = 0, hasRootNode = "http://rdfh.ch/lists/00FF/d19af9ab" ) @@ -86,7 +86,7 @@ object SharedListsTestDataADM { id = "http://rdfh.ch/lists/0001/treeList01", name = Some("Tree list node 01"), labels = StringLiteralSequenceV2(Vector(StringLiteralV2(value = "Tree list node 01", language = Some("en")))), - comments = Some(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), + comments = StringLiteralSequenceV2(Vector.empty[StringLiteralV2]), position = 0, hasRootNode = "http://rdfh.ch/lists/0001/treeList" ) From e1c3c66aa3b38b25b9d2c52725685a8b646f8ebe Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 20 Oct 2021 11:10:37 +0200 Subject: [PATCH 13/32] fix tests --- .../webapi/responders/admin/ListsResponderADM.scala | 2 +- .../e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 276f86a6cd..e9acd94966 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -1426,7 +1426,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde apiRequestID: UUID ): Future[NodeInfoGetResponseADM] = { def verifyUpdatedNode(updatedNode: ListNodeInfoADM): Unit = - if (updatedNode.getComments.stringLiterals.diff(changeNodeCommentsRequest.comments.get.value).nonEmpty) + if (updatedNode.getComments.stringLiterals == changeNodeCommentsRequest.comments.map(_.value)) throw UpdateNotPerformedException("Node's 'comments' were not updated. Please report this as a possible bug.") /** diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala index 4cc389ed28..d6492a7350 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala @@ -221,9 +221,8 @@ class UpdateListItemsRouteADME2ESpec ) ) } - "delete node comments" in { -// this should fail because in root nodes comments are required - change on line 240 -// add another test which allow delete comments for child node + "not delete root node comments" in { + // TODO: add another test which allow delete comments for child node val deleteCommentsLabels = s"""{ @@ -238,14 +237,14 @@ class UpdateListItemsRouteADME2ESpec val response: HttpResponse = singleAwaitingRequest(request) log.debug(s"response: ${response.toString}") response.status should be(StatusCodes.OK) -// response.status should be(StatusCodes.BadRequest) val receivedListInfo: ListRootNodeInfoADM = AkkaHttpUtils.httpResponseToJson(response).fields("listinfo").convertTo[ListRootNodeInfoADM] receivedListInfo.projectIri should be(SharedTestDataADM.ANYTHING_PROJECT_IRI) val comments: Seq[StringLiteralV2] = receivedListInfo.comments.stringLiterals - comments.size should be(0) + comments.size should be(1) + comments(0).toString should be("nya kommentarer") } } From 0d0cbde1f84d60ef75abe8b83d779f5c6a0a61be Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 20 Oct 2021 12:37:25 +0200 Subject: [PATCH 14/32] update tests --- .../UpdateListItemsRouteADME2ESpec.scala | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala index d6492a7350..4151add68f 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala @@ -222,9 +222,7 @@ class UpdateListItemsRouteADME2ESpec ) } "not delete root node comments" in { - // TODO: add another test which allow delete comments for child node - - val deleteCommentsLabels = + val deleteComments = s"""{ | "comments": [] |}""".stripMargin @@ -232,7 +230,7 @@ class UpdateListItemsRouteADME2ESpec val request = Put( baseApiUrl + s"/admin/lists/" + encodedListUrl + "/comments", - HttpEntity(ContentTypes.`application/json`, deleteCommentsLabels) + HttpEntity(ContentTypes.`application/json`, deleteComments) ) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) val response: HttpResponse = singleAwaitingRequest(request) log.debug(s"response: ${response.toString}") @@ -244,7 +242,7 @@ class UpdateListItemsRouteADME2ESpec val comments: Seq[StringLiteralV2] = receivedListInfo.comments.stringLiterals comments.size should be(1) - comments(0).toString should be("nya kommentarer") + comments should contain(StringLiteralV2(value = "nya kommentarer", language = Some("se"))) } } @@ -383,6 +381,41 @@ class UpdateListItemsRouteADME2ESpec ) } +// "delete child node comments" in { +//// this test should pass, but deleting comments for both root and child nodes are not working now using PUT and [] +//// TODO: implement DELETE method (only for child) +// val deleteNodeComments = +// s"""{ +// | "comments": [] +// |}""".stripMargin +// +// clientTestDataCollector.addFile( +// TestDataFileContent( +// filePath = TestDataFilePath( +// directoryPath = clientTestDataPath, +// filename = "update-childNode-comments-request", +// fileExtension = "json" +// ), +// text = deleteNodeComments +// ) +// ) +// +// val encodedListUrl = java.net.URLEncoder.encode(treeChildNode.id, "utf-8") +// +// val request = Put( +// baseApiUrl + s"/admin/lists/" + encodedListUrl + "/comments", +// HttpEntity(ContentTypes.`application/json`, deleteNodeComments) +// ) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) +// val response: HttpResponse = singleAwaitingRequest(request) +// +// response.status should be(StatusCodes.OK) +// +// val receivedNodeInfo: ListChildNodeInfoADM = +// AkkaHttpUtils.httpResponseToJson(response).fields("nodeinfo").convertTo[ListChildNodeInfoADM] +// val comments: Seq[StringLiteralV2] = receivedNodeInfo.comments.stringLiterals +// comments.size should be(0) +// } + "not update the position of a node if given IRI is invalid" in { val parentIri = "http://rdfh.ch/lists/0001/notUsedList01" val newPosition = 1 From 2eab17f7546c783f9a878deccf3d4fcbe06dc384 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 20 Oct 2021 14:54:14 +0200 Subject: [PATCH 15/32] refactor list value objects + add tests --- .../listsmessages/ListPayloadsADM.scala | 10 +- .../listsmessages/ListsMessagesADM.scala | 1 + .../valueObjects/ListsValueObjectsADM.scala | 57 ++++ .../valueObjects/ValueObjectsADM.scala | 42 --- .../responders/admin/ListsResponderADM.scala | 4 +- .../admin/lists/NewListsRouteADMFeature.scala | 10 +- .../admin/lists/OldListsRouteADMFeature.scala | 14 +- .../admin/lists/UpdateListItemsRouteADM.scala | 5 +- .../admin/responder/valueObjects/BUILD.bazel | 1 + .../ListsValueObjectsADMSpec.scala | 260 ++++++++++++++++++ .../admin/ListsResponderADMSpec.scala | 18 +- 11 files changed, 349 insertions(+), 73 deletions(-) create mode 100644 webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala create mode 100644 webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index 22cf8111a2..ca0f13c75e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -1,7 +1,7 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} /** * Root and Child Node creation payloads @@ -12,7 +12,7 @@ object NodeCreatePayloadADM { id: Option[IRI] = None, parentNodeIri: Option[IRI] = None, projectIri: IRI, - name: Option[Name] = None, + name: Option[ListName] = None, position: Option[Position] = None, labels: Labels, comments: Comments @@ -21,7 +21,7 @@ object NodeCreatePayloadADM { id: Option[IRI] = None, parentNodeIri: Option[IRI] = None, projectIri: IRI, - name: Option[Name] = None, + name: Option[ListName] = None, position: Option[Position] = None, labels: Labels, comments: Option[Comments] = None @@ -36,7 +36,7 @@ final case class NodeInfoChangePayloadADM( projectIri: IRI, hasRootNode: Option[IRI] = None, position: Option[Position] = None, - name: Option[Name] = None, + name: Option[ListName] = None, labels: Option[Labels] = None, comments: Option[Comments] = None ) @@ -45,7 +45,7 @@ final case class NodeInfoChangePayloadADM( * Node Name update payload */ final case class NodeNameChangePayloadADM( - name: Name + name: ListName ) /** diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index dece6a6c5e..920daad5ec 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -101,6 +101,7 @@ case class CreateNodeApiRequestADM( labels: Seq[StringLiteralV2], comments: Seq[StringLiteralV2] ) extends ListADMJsonProtocol { +// TODO: are below checks necessary anymore? private val stringFormatter = StringFormatter.getInstanceForConstantOntologies stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list node IRI")) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala new file mode 100644 index 0000000000..324b3f45d1 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -0,0 +1,57 @@ +package org.knora.webapi.messages.admin.responder.valueObjects + +import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.INVALID_POSITION +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 + +/** + * ListName value object. + */ +sealed abstract case class ListName private (value: String) +object ListName { + def create(value: String): Either[Throwable, ListName] = + if (value.isEmpty) { + Left(BadRequestException("Missing List Name")) + } else { + Right(new ListName(value) {}) + } +} + +/** + * Position value object. + */ +sealed abstract case class Position private (value: Int) +object Position { + def create(value: Int): Either[Throwable, Position] = + if (value < -1) { // TODO: what should be the criteria? + Left(BadRequestException(INVALID_POSITION)) + } else { + Right(new Position(value) {}) + } +} + +/** + * Labels value object. + */ +sealed abstract case class Labels private (value: Seq[StringLiteralV2]) +object Labels { + def create(value: Seq[StringLiteralV2]): Either[Throwable, Labels] = + if (value.isEmpty) { + Left(BadRequestException("Missing labels")) + } else { + Right(new Labels(value) {}) + } +} + +/** + * Comments value object. + */ +sealed abstract case class Comments private (value: Seq[StringLiteralV2]) +object Comments { + def create(value: Seq[StringLiteralV2]): Either[Throwable, Comments] = + if (value.isEmpty) { + Left(BadRequestException("Missing comments")) + } else { + Right(new Comments(value) {}) + } +} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala index 30fbaace6f..fd422202b4 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala @@ -4,7 +4,6 @@ import org.knora.webapi.LanguageCodes import org.knora.webapi.exceptions.{AssertionException, BadRequestException} import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.INVALID_POSITION import zio.prelude.Validation import scala.util.matching.Regex @@ -216,47 +215,6 @@ object Logo { self => } } -/** Lists value objects */ - -/** - * Labels value object. - */ -sealed abstract case class Labels private (value: Seq[StringLiteralV2]) -object Labels { - def create(value: Seq[StringLiteralV2]): Either[Throwable, Labels] = - if (value.isEmpty) { - Left(BadRequestException("Missing labels")) - } else { - Right(new Labels(value) {}) - } -} - -/** - * Comments value object. - */ -sealed abstract case class Comments private (value: Seq[StringLiteralV2]) -object Comments { - def create(value: Seq[StringLiteralV2]): Either[Throwable, Comments] = - if (value.isEmpty) { - Left(BadRequestException("Missing comments")) - } else { - Right(new Comments(value) {}) - } -} - -/** - * Position value object. - */ -sealed abstract case class Position private (value: Int) -object Position { - def create(value: Int): Either[Throwable, Position] = - if (value < -1) { // TODO: what should be the criteria? - Left(BadRequestException(INVALID_POSITION)) - } else { - Right(new Position(value) {}) - } -} - /** Shared value objects */ /** diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index e9acd94966..419040d1f3 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -40,7 +40,7 @@ import org.knora.webapi.messages.util.{KnoraSystemInstances, ResponderData} import org.knora.webapi.messages.{OntologyConstants, SmartIri} import org.knora.webapi.responders.Responder.handleUnexpectedMessage import org.knora.webapi.responders.{IriLocker, Responder} -import org.knora.webapi.messages.admin.responder.valueObjects.Name +import org.knora.webapi.messages.admin.responder.valueObjects.ListName import scala.annotation.tailrec import scala.concurrent.Future @@ -2134,7 +2134,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * @param listNodeName the list node name. * @return a [[Boolean]]. */ - private def listNodeNameIsProjectUnique(projectIri: IRI, listNodeName: Option[Name]): Future[Boolean] = + private def listNodeNameIsProjectUnique(projectIri: IRI, listNodeName: Option[ListName]): Future[Boolean] = listNodeName match { case Some(name) => for { diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 6a2c4c2f67..0b22578b70 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -34,7 +34,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload RootNodeCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -171,8 +171,8 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) throw BadRequestException(s"Invalid parent node IRI") ) - val maybeName: Option[Name] = apiRequest.name match { - case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + val maybeName: Option[ListName] = apiRequest.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None } @@ -346,8 +346,8 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val projectIri = stringFormatter .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) - val maybeName: Option[Name] = apiRequest.name match { - case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + val maybeName: Option[ListName] = apiRequest.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index c05df3797e..92a9ad7a30 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -37,7 +37,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload RootNodeCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -138,8 +138,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => - val maybeName: Option[Name] = apiRequest.name match { - case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + val maybeName: Option[ListName] = apiRequest.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None } @@ -269,8 +269,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val listIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) - val maybeName: Option[Name] = apiRequest.name match { - case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + val maybeName: Option[ListName] = apiRequest.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None } @@ -366,8 +366,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val projectIri = stringFormatter .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) - val maybeName: Option[Name] = apiRequest.name match { - case Some(value) => Some(Name.create(value).fold(e => throw e, v => v)) + val maybeName: Option[ListName] = apiRequest.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala index 31d39bd1e5..fa31c7523d 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/UpdateListItemsRouteADM.scala @@ -28,7 +28,7 @@ import javax.ws.rs.Path import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} import org.knora.webapi.messages.admin.responder.listsmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.{Name, Labels, Comments} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -91,13 +91,12 @@ class UpdateListItemsRouteADM(routeData: KnoraRouteData) stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param node IRI: $iri")) val namePayload: NodeNameChangePayloadADM = - NodeNameChangePayloadADM(Name.create(apiRequest.name).fold(e => throw e, v => v)) + NodeNameChangePayloadADM(ListName.create(apiRequest.name).fold(e => throw e, v => v)) val requestMessage: Future[NodeNameChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) } yield NodeNameChangeRequestADM( nodeIri = nodeIri, -// payload for name changeNodeNameRequest = namePayload, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel index af90934728..da363f069d 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel @@ -7,6 +7,7 @@ scala_test( name = "ValueObjectsADMSpec", size = "small", # 60s srcs = [ + "ListsValueObjectsADMSpec.scala", "ValueObjectsADMSpec.scala", ], data = [ diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala new file mode 100644 index 0000000000..28f2da5d15 --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -0,0 +1,260 @@ +/* + * Copyright © 2015-2021 Data and Service Center for the Humanities (DaSCH) + * + * This file is part of Knora. + * + * Knora is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knora is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with Knora. If not, see . + */ + +package org.knora.webapi.messages.admin.responder.valueObjects + +import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ + ChildNodeCreatePayloadADM, + RootNodeCreatePayloadADM +} +import org.knora.webapi.messages.admin.responder.listsmessages.{CreateNodeApiRequestADM, NodeCreatePayloadADM} +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 +import org.knora.webapi.{IRI, UnitSpec} +import org.scalatest.enablers.Messaging.messagingNatureOfThrowable + +/** + * This spec is used to test the creation of value objects of the [[ListsValueObjectsADM]]. + */ +class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { + + private implicit val stringFormatter: StringFormatter = StringFormatter.getInstanceForConstantOntologies + + /** + * Convenience method returning the NodeCreatePayloadADM from the [[CreateNodeApiRequestADM]] object + * + * @param createNodeApiRequestADM the [[CreateNodeApiRequestADM]] object + * @return a [[NodeCreatePayloadADM]] + */ + private def createRootNodeCreatePayloadADM( + createNodeApiRequestADM: CreateNodeApiRequestADM + ): RootNodeCreatePayloadADM = { + val maybeName: Option[ListName] = createNodeApiRequestADM.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybePosition: Option[Position] = createNodeApiRequestADM.position match { + case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + case None => None + } + + RootNodeCreatePayloadADM( + id = stringFormatter.validateAndEscapeOptionalIri( + createNodeApiRequestADM.id, + throw BadRequestException(s"Invalid custom node IRI") + ), + parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( + createNodeApiRequestADM.parentNodeIri, + throw BadRequestException(s"Invalid parent node IRI") + ), + projectIri = stringFormatter + .validateAndEscapeProjectIri( + createNodeApiRequestADM.projectIri, + throw BadRequestException(s"Invalid project IRI") + ), + name = maybeName, + position = maybePosition, + labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), + comments = Comments.create(createNodeApiRequestADM.comments).fold(e => throw e, v => v) + ) + } + + /** + * Convenience method returning the [[RootNodeCreatePayloadADM]] object + * + * @param id the optional custom IRI of the list node. + * @param parentNodeIri the optional IRI of the parent node. + * @param projectIri the IRI of the project. + * @param name the optional name of the list node. + * @param position the optional position of the node. + * @param labels labels of the list node. + * @param comments comments of the list node. + * @return a [[RootNodeCreatePayloadADM]] + */ + private def createRootNodeApiRequestADM( + id: Option[IRI] = None, + parentNodeIri: Option[IRI] = None, + projectIri: IRI = "http://rdfh.ch/projects/0001", + name: Option[String] = None, + position: Option[Int] = None, + labels: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New label", language = Some("en"))), + comments: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New comment", language = Some("en"))) + ): CreateNodeApiRequestADM = CreateNodeApiRequestADM(id, parentNodeIri, projectIri, name, position, labels, comments) + + "When the RootNodeCreatePayloadADM case class is created it" should { + "create a valid RootNodeCreatePayloadADM" in { + + val request = createRootNodeApiRequestADM() + + val rootNodeCreatePayloadADM = createRootNodeCreatePayloadADM(request) + + rootNodeCreatePayloadADM.id should equal(request.id) + rootNodeCreatePayloadADM.parentNodeIri should equal(request.parentNodeIri) + rootNodeCreatePayloadADM.projectIri should equal(request.projectIri) + rootNodeCreatePayloadADM.name.map(_.value) should equal(request.name) + rootNodeCreatePayloadADM.position.map(_.value) should equal(request.position) + rootNodeCreatePayloadADM.labels.value should equal(request.labels) + rootNodeCreatePayloadADM.comments.value should equal(request.comments) + + val otherRequest = createRootNodeApiRequestADM( + id = Some("http://rdfh.ch/lists/otherlistcustomid"), + parentNodeIri = None, + projectIri = "http://rdfh.ch/projects/0002", + name = Some("Uther Name"), + position = None, + labels = Seq(StringLiteralV2(value = "Other label", language = Some("en"))), + comments = Seq(StringLiteralV2(value = "Other comment", language = Some("en"))) + ) + + val otherRootNodeCreatePayloadADM = createRootNodeCreatePayloadADM(otherRequest) + + otherRootNodeCreatePayloadADM.id should equal(otherRequest.id) + otherRootNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) + otherRootNodeCreatePayloadADM.projectIri should equal(otherRequest.projectIri) + otherRootNodeCreatePayloadADM.name.map(_.value) should equal(otherRequest.name) + otherRootNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) + otherRootNodeCreatePayloadADM.labels.value should equal(otherRequest.labels) + otherRootNodeCreatePayloadADM.comments.value should equal(otherRequest.comments) + + otherRootNodeCreatePayloadADM.id should not equal request.id +// otherRootNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) + otherRootNodeCreatePayloadADM.projectIri should not equal (request.projectIri) + otherRootNodeCreatePayloadADM.name.get.value should not equal (request.name) +// otherRootNodeCreatePayloadADM.position.get.value should equal(otherRequest.position) + otherRootNodeCreatePayloadADM.labels.value should not equal (request.labels) + otherRootNodeCreatePayloadADM.comments.value should not equal (request.comments) + } + } + + /** + * Convenience method returning the NodeCreatePayloadADM from the [[CreateNodeApiRequestADM]] object + * + * @param createNodeApiRequestADM the [[CreateNodeApiRequestADM]] object + * @return a [[NodeCreatePayloadADM]] + */ + private def createChildNodeCreatePayloadADM( + createNodeApiRequestADM: CreateNodeApiRequestADM + ): ChildNodeCreatePayloadADM = { + val maybeName: Option[ListName] = createNodeApiRequestADM.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) + case None => None + } + + val maybePosition: Option[Position] = createNodeApiRequestADM.position match { + case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + case None => None + } + +// val maybeComments: Option[Comments] = createNodeApiRequestADM.comments match { +// case Some(value) => Some(Comments.create(value).fold(e => throw e, v => v)) +// case None => None +// } + + ChildNodeCreatePayloadADM( + id = stringFormatter.validateAndEscapeOptionalIri( + createNodeApiRequestADM.id, + throw BadRequestException(s"Invalid custom node IRI") + ), + parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( + createNodeApiRequestADM.parentNodeIri, + throw BadRequestException(s"Invalid parent node IRI") + ), + projectIri = stringFormatter + .validateAndEscapeProjectIri( + createNodeApiRequestADM.projectIri, + throw BadRequestException(s"Invalid project IRI") + ), + name = maybeName, + position = maybePosition, + labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), + comments = Some(Comments.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v)) + ) + } + + /** + * Convenience method returning the [[ChildNodeCreatePayloadADM]] object + * + * @param id the optional custom IRI of the list node. + * @param parentNodeIri the optional IRI of the parent node. + * @param projectIri the IRI of the project. + * @param name the optional name of the list node. + * @param position the optional position of the node. + * @param labels labels of the list node. + * @param comments comments of the list node. + * @return a [[ChildNodeCreatePayloadADM]] + */ + private def createChildNodeApiRequestADM( + id: Option[IRI] = None, + parentNodeIri: Option[IRI] = None, + projectIri: IRI = "http://rdfh.ch/projects/0001", + name: Option[String] = None, + position: Option[Int] = None, + labels: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New label", language = Some("en"))), + comments: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New comment", language = Some("en"))) + ): CreateNodeApiRequestADM = CreateNodeApiRequestADM(id, parentNodeIri, projectIri, name, position, labels, comments) + + "When the ChildNodeCreatePayloadADM case class is created it" should { + "create a valid ChildNodeCreatePayloadADM" in { + + val request = createChildNodeApiRequestADM() + + val childNodeCreatePayloadADM = createChildNodeCreatePayloadADM(request) + + childNodeCreatePayloadADM.id should equal(request.id) + childNodeCreatePayloadADM.parentNodeIri should equal(request.parentNodeIri) + childNodeCreatePayloadADM.projectIri should equal(request.projectIri) + childNodeCreatePayloadADM.name.map(_.value) should equal(request.name) + childNodeCreatePayloadADM.position.map(_.value) should equal(request.position) + childNodeCreatePayloadADM.labels.value should equal(request.labels) +// TODO: bring below back after separating ChildNodeCreateApiRequestADM from CreateNodeApiRequestADM +// childNodeCreatePayloadADM.comments.map(_.value) should equal(request.comments) + + val otherRequest = createChildNodeApiRequestADM( + id = Some("http://rdfh.ch/lists/otherlistcustomid"), + parentNodeIri = None, + projectIri = "http://rdfh.ch/projects/0002", + name = Some("Uther Name"), + position = None, + labels = Seq(StringLiteralV2(value = "Other label", language = Some("en"))), + comments = Seq(StringLiteralV2(value = "Other comment", language = Some("en"))) + ) + + val otherChildNodeCreatePayloadADM = createChildNodeCreatePayloadADM(otherRequest) + + otherChildNodeCreatePayloadADM.id should equal(otherRequest.id) + otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) + otherChildNodeCreatePayloadADM.projectIri should equal(otherRequest.projectIri) + otherChildNodeCreatePayloadADM.name.map(_.value) should equal(otherRequest.name) + otherChildNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) + otherChildNodeCreatePayloadADM.labels.value should equal(otherRequest.labels) +// TODO: bring below back after separating ChildNodeCreateApiRequestADM from CreateNodeApiRequestADM +// otherChildNodeCreatePayloadADM.comments.map(_.value) should equal(otherRequest.comments) + + otherChildNodeCreatePayloadADM.id should not equal request.id + // otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) + otherChildNodeCreatePayloadADM.projectIri should not equal (request.projectIri) + otherChildNodeCreatePayloadADM.name.get.value should not equal (request.name) + // otherChildNodeCreatePayloadADM.position.get.value should equal(otherRequest.position) + otherChildNodeCreatePayloadADM.labels.value should not equal (request.labels) + otherChildNodeCreatePayloadADM.comments.map(_.value) should not equal (request.comments) + } + } +} diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index d7f9821591..05688a12ef 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -35,7 +35,7 @@ import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, Strin import org.knora.webapi.sharedtestdata.SharedTestDataV1._ import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} import org.knora.webapi.util.MutableTestIri -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} import scala.concurrent.duration._ @@ -182,7 +182,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with responderManager ! ListCreateRequestADM( createRootNode = RootNodeCreatePayloadADM( projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("neuelistename").fold(e => throw e, v => v)), + name = Some(ListName.create("neuelistename").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) .fold(e => throw e, v => v), @@ -223,7 +223,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with responderManager ! ListCreateRequestADM( createRootNode = RootNodeCreatePayloadADM( projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), + name = Some(ListName.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = labelWithSpecialCharacter, language = Some("de")))) .fold(e => throw e, v => v), @@ -264,7 +264,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with changeNodeRequest = NodeInfoChangePayloadADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("updated name").fold(e => throw e, v => v)), + name = Some(ListName.create("updated name").fold(e => throw e, v => v)), labels = Some( Labels .create( @@ -317,7 +317,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with } "not update basic list information if name is duplicate" in { - val name = Some(Name.create("sommer").fold(e => throw e, v => v)) + val name = Some(ListName.create("sommer").fold(e => throw e, v => v)) responderManager ! NodeInfoChangeRequestADM( listIri = newListIri.get, changeNodeRequest = NodeInfoChangePayloadADM( @@ -343,7 +343,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("first").fold(e => throw e, v => v)), + name = Some(ListName.create("first").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) .fold(e => throw e, v => v), @@ -397,7 +397,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("second").fold(e => throw e, v => v)), + name = Some(ListName.create("second").fold(e => throw e, v => v)), position = Some(Position.create(0).fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New Second Child List Node Value", language = Some("en")))) @@ -450,7 +450,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(secondChildIri.get), projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("third").fold(e => throw e, v => v)), + name = Some(ListName.create("third").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) .fold(e => throw e, v => v), @@ -503,7 +503,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), projectIri = IMAGES_PROJECT_IRI, - name = Some(Name.create("fourth").fold(e => throw e, v => v)), + name = Some(ListName.create("fourth").fold(e => throw e, v => v)), position = givenPosition, labels = Labels .create(Seq(StringLiteralV2(value = "New Fourth Child List Node Value", language = Some("en")))) From e32fe4926b60ff03592e4cc462ecef37c0c445fc Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 22 Oct 2021 11:42:20 +0200 Subject: [PATCH 16/32] remove redundant fields from RootNodeCreatePayloadADM --- .../listsmessages/ListPayloadsADM.scala | 3 +- .../listsmessages/ListsMessagesADM.scala | 4 +- .../responders/admin/ListsResponderADM.scala | 37 +++++++++++++----- .../admin/lists/NewListsRouteADMFeature.scala | 2 - .../admin/lists/OldListsRouteADMFeature.scala | 5 --- .../ListsValueObjectsADMSpec.scala | 38 ++++++++----------- 6 files changed, 45 insertions(+), 44 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index ca0f13c75e..c486f67682 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -10,10 +10,8 @@ sealed trait NodeCreatePayloadADM object NodeCreatePayloadADM { final case class RootNodeCreatePayloadADM( id: Option[IRI] = None, - parentNodeIri: Option[IRI] = None, projectIri: IRI, name: Option[ListName] = None, - position: Option[Position] = None, labels: Labels, comments: Comments ) extends NodeCreatePayloadADM @@ -59,5 +57,6 @@ final case class NodeLabelsChangePayloadADM( * Node Comments update payload */ final case class NodeCommentsChangePayloadADM( +// TODO: remove Option here comments: Option[Comments] = None ) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 920daad5ec..afdd981c2b 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -75,7 +75,7 @@ case class CreateListApiRequestADM( def toJsValue: JsValue = createListApiRequestADMFormat.write(this) } - +// TODO: naming is wrong, below are used for both creating LIST and NODES, root node should be changed to LIST child node to NODE /** * Represents an API request payload that asks the Knora API server to create a new node. * If the IRI of the parent node is given, the new node is attached to the parent node as a sublist node. @@ -101,7 +101,7 @@ case class CreateNodeApiRequestADM( labels: Seq[StringLiteralV2], comments: Seq[StringLiteralV2] ) extends ListADMJsonProtocol { -// TODO: are below checks necessary anymore? +// TODO: are below checks necessary anymore? CORRECT! but move all checks to value objects private val stringFormatter = StringFormatter.getInstanceForConstantOntologies stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list node IRI")) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 419040d1f3..bcbb2c9833 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -857,16 +857,34 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde println("ZZZZZ-createNode", createNodeRequest) - val (id, parentNodeIri, projectIri, name, position) = createNodeRequest match { - case RootNodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, _, _) => - (id, parentNodeIri, projectIri, name, position) - case ChildNodeCreatePayloadADM(id, parentNodeIri, projectIri, name, position, _, _) => - (id, parentNodeIri, projectIri, name, position) + val id = createNodeRequest match { + case root: NodeCreatePayloadADM.RootNodeCreatePayloadADM => root.id + case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.id + } + + val parentNodeIri = createNodeRequest match { + case _: NodeCreatePayloadADM.RootNodeCreatePayloadADM => None + case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.parentNodeIri + } + + val projectIri = createNodeRequest match { + case root: NodeCreatePayloadADM.RootNodeCreatePayloadADM => root.projectIri + case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.projectIri + } + + val name = createNodeRequest match { + case root: NodeCreatePayloadADM.RootNodeCreatePayloadADM => root.name + case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.name + } + + val position = createNodeRequest match { + case _: NodeCreatePayloadADM.RootNodeCreatePayloadADM => None + case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.position } def getPositionOfNewChild(children: Seq[ListChildNodeADM]): Int = { if (position.exists(_.value > children.size)) { - val givenPosition = position.get + val givenPosition = position.map(_.value) throw BadRequestException( s"Invalid position given $givenPosition, maximum allowed position is = ${children.size}." ) @@ -953,6 +971,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde name ) _ = if (!projectUniqueNodeName) { +// TODO: all Option.get occurrences should be replaced by map val escapedName = name.get.value val unescapedName = stringFormatter.fromSparqlEncodedString(escapedName) throw BadRequestException( @@ -984,10 +1003,8 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde createNewListSparqlString: String = createNodeRequest match { case NodeCreatePayloadADM.RootNodeCreatePayloadADM( _, - parentNodeIri, projectIri, name, - position, labels, comments ) => { @@ -998,9 +1015,9 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde listClassIri = OntologyConstants.KnoraBase.ListNode, projectIri = projectIri, nodeIri = newListNodeIri, - parentNodeIri = parentNodeIri, + parentNodeIri = None, rootNodeIri = rootNodeIri, - position = position.map(_.value), + position = None, maybeName = name.map(_.value), maybeLabels = labels.value, maybeComments = Some(comments.value) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 0b22578b70..451b98a7d3 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -189,10 +189,8 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val createRootNodePayloadADM: RootNodeCreatePayloadADM = RootNodeCreatePayloadADM( id, - parentNodeIri, projectIri, name = maybeName, - position = maybePosition, labels, comments ) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 92a9ad7a30..f9fdbc2a35 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -156,13 +156,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) apiRequest.id, throw BadRequestException(s"Invalid custom node IRI") ), - parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.parentNodeIri, - throw BadRequestException(s"Invalid parent node IRI") - ), projectIri, name = maybeName, - position = maybePosition, labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) ) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index 28f2da5d15..8a7aa8ca26 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -35,6 +35,8 @@ import org.scalatest.enablers.Messaging.messagingNatureOfThrowable */ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { +// TODO: these test should be simplified - UNIT TESTS about value objects only + private implicit val stringFormatter: StringFormatter = StringFormatter.getInstanceForConstantOntologies /** @@ -61,17 +63,12 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { createNodeApiRequestADM.id, throw BadRequestException(s"Invalid custom node IRI") ), - parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( - createNodeApiRequestADM.parentNodeIri, - throw BadRequestException(s"Invalid parent node IRI") - ), projectIri = stringFormatter .validateAndEscapeProjectIri( createNodeApiRequestADM.projectIri, throw BadRequestException(s"Invalid project IRI") ), name = maybeName, - position = maybePosition, labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), comments = Comments.create(createNodeApiRequestADM.comments).fold(e => throw e, v => v) ) @@ -107,10 +104,8 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { val rootNodeCreatePayloadADM = createRootNodeCreatePayloadADM(request) rootNodeCreatePayloadADM.id should equal(request.id) - rootNodeCreatePayloadADM.parentNodeIri should equal(request.parentNodeIri) rootNodeCreatePayloadADM.projectIri should equal(request.projectIri) rootNodeCreatePayloadADM.name.map(_.value) should equal(request.name) - rootNodeCreatePayloadADM.position.map(_.value) should equal(request.position) rootNodeCreatePayloadADM.labels.value should equal(request.labels) rootNodeCreatePayloadADM.comments.value should equal(request.comments) @@ -127,20 +122,16 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { val otherRootNodeCreatePayloadADM = createRootNodeCreatePayloadADM(otherRequest) otherRootNodeCreatePayloadADM.id should equal(otherRequest.id) - otherRootNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) otherRootNodeCreatePayloadADM.projectIri should equal(otherRequest.projectIri) otherRootNodeCreatePayloadADM.name.map(_.value) should equal(otherRequest.name) - otherRootNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) otherRootNodeCreatePayloadADM.labels.value should equal(otherRequest.labels) otherRootNodeCreatePayloadADM.comments.value should equal(otherRequest.comments) otherRootNodeCreatePayloadADM.id should not equal request.id -// otherRootNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) - otherRootNodeCreatePayloadADM.projectIri should not equal (request.projectIri) - otherRootNodeCreatePayloadADM.name.get.value should not equal (request.name) -// otherRootNodeCreatePayloadADM.position.get.value should equal(otherRequest.position) - otherRootNodeCreatePayloadADM.labels.value should not equal (request.labels) - otherRootNodeCreatePayloadADM.comments.value should not equal (request.comments) + otherRootNodeCreatePayloadADM.projectIri should not equal request.projectIri + otherRootNodeCreatePayloadADM.name.get.value should not equal request.name + otherRootNodeCreatePayloadADM.labels.value should not equal request.labels + otherRootNodeCreatePayloadADM.comments.value should not equal request.comments } } @@ -208,8 +199,9 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { name: Option[String] = None, position: Option[Int] = None, labels: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New label", language = Some("en"))), - comments: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New comment", language = Some("en"))) - ): CreateNodeApiRequestADM = CreateNodeApiRequestADM(id, parentNodeIri, projectIri, name, position, labels, comments) + comments: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "", language = None)) + ): CreateNodeApiRequestADM = + CreateNodeApiRequestADM(id, parentNodeIri, projectIri, name, position, labels, comments) "When the ChildNodeCreatePayloadADM case class is created it" should { "create a valid ChildNodeCreatePayloadADM" in { @@ -249,12 +241,12 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { // otherChildNodeCreatePayloadADM.comments.map(_.value) should equal(otherRequest.comments) otherChildNodeCreatePayloadADM.id should not equal request.id - // otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) - otherChildNodeCreatePayloadADM.projectIri should not equal (request.projectIri) - otherChildNodeCreatePayloadADM.name.get.value should not equal (request.name) - // otherChildNodeCreatePayloadADM.position.get.value should equal(otherRequest.position) - otherChildNodeCreatePayloadADM.labels.value should not equal (request.labels) - otherChildNodeCreatePayloadADM.comments.map(_.value) should not equal (request.comments) +// otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) + otherChildNodeCreatePayloadADM.projectIri should not equal request.projectIri + otherChildNodeCreatePayloadADM.name.get.value should not equal request.name +// otherChildNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) + otherChildNodeCreatePayloadADM.labels.value should not equal request.labels + otherChildNodeCreatePayloadADM.comments.map(_.value) should not equal request.comments } } } From 51347b719f5bc4e9e01ec8d2d683003a2c5689fe Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 22 Oct 2021 12:55:44 +0200 Subject: [PATCH 17/32] refactor list naming + remove redundand request type --- .../listsmessages/ListPayloadsADM.scala | 4 +- .../listsmessages/ListsMessagesADM.scala | 43 +------------------ .../responders/admin/ListsResponderADM.scala | 32 +++----------- .../admin/lists/NewListsRouteADMFeature.scala | 6 +-- .../admin/lists/OldListsRouteADMFeature.scala | 6 +-- .../listsmessages/ListsMessagesADMSpec.scala | 26 +++++------ .../ListsValueObjectsADMSpec.scala | 26 +++++------ .../admin/ListsResponderADMSpec.scala | 6 +-- 8 files changed, 46 insertions(+), 103 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index c486f67682..3e60801578 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -4,11 +4,11 @@ import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} /** - * Root and Child Node creation payloads + * List (parent node, former root node) and Node (former child node) creation payloads */ sealed trait NodeCreatePayloadADM object NodeCreatePayloadADM { - final case class RootNodeCreatePayloadADM( + final case class ListCreatePayloadADM( id: Option[IRI] = None, projectIri: IRI, name: Option[ListName] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index afdd981c2b..ff111bd441 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -22,7 +22,7 @@ package org.knora.webapi.messages.admin.responder.listsmessages import java.util.UUID import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import org.knora.webapi._ -import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} +import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ @@ -40,44 +40,7 @@ import spray.json._ // API requests /** - * Represents an API request payload that asks the Knora API server to create a new list. At least one - * label needs to be supplied. - * - * @param id the optional custom list IRI. - * @param projectIri the IRI of the project the list belongs to. - * @param name the optional name of the list. - * @param labels the list's labels. - * @param comments the list's comments. - */ -case class CreateListApiRequestADM( - id: Option[IRI] = None, - projectIri: IRI, - name: Option[String] = None, - labels: Seq[StringLiteralV2], - comments: Seq[StringLiteralV2] // descriptions -) extends ListADMJsonProtocol { - - private val stringFormatter = StringFormatter.getInstanceForConstantOntologies - - stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list IRI")) - - if (projectIri.isEmpty) { - throw BadRequestException(PROJECT_IRI_MISSING_ERROR) - } - - if (!stringFormatter.isKnoraProjectIriStr(projectIri)) { - throw BadRequestException(PROJECT_IRI_INVALID_ERROR) - } - - if (labels.isEmpty) { - throw BadRequestException(LABEL_MISSING_ERROR) - } - - def toJsValue: JsValue = createListApiRequestADMFormat.write(this) -} -// TODO: naming is wrong, below are used for both creating LIST and NODES, root node should be changed to LIST child node to NODE -/** - * Represents an API request payload that asks the Knora API server to create a new node. + * Represents an API request payload that asks the Knora API server to create a new list or child node. * If the IRI of the parent node is given, the new node is attached to the parent node as a sublist node. * If a specific position is given, insert the child node there. Otherwise, the newly created list node will be appended * to the end of the list of children. @@ -1358,8 +1321,6 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with } } - implicit val createListApiRequestADMFormat: RootJsonFormat[CreateListApiRequestADM] = - jsonFormat(CreateListApiRequestADM, "id", "projectIri", "name", "labels", "comments") implicit val createListNodeApiRequestADMFormat: RootJsonFormat[CreateNodeApiRequestADM] = jsonFormat(CreateNodeApiRequestADM, "id", "parentNodeIri", "projectIri", "name", "position", "labels", "comments") implicit val changeListInfoApiRequestADMFormat: RootJsonFormat[ChangeNodeInfoApiRequestADM] = jsonFormat( diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index bcbb2c9833..5878344391 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -29,7 +29,7 @@ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ ChildNodeCreatePayloadADM, - RootNodeCreatePayloadADM + ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectGetADM, ProjectIdentifierADM} @@ -857,29 +857,11 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde println("ZZZZZ-createNode", createNodeRequest) - val id = createNodeRequest match { - case root: NodeCreatePayloadADM.RootNodeCreatePayloadADM => root.id - case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.id - } - - val parentNodeIri = createNodeRequest match { - case _: NodeCreatePayloadADM.RootNodeCreatePayloadADM => None - case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.parentNodeIri - } - - val projectIri = createNodeRequest match { - case root: NodeCreatePayloadADM.RootNodeCreatePayloadADM => root.projectIri - case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.projectIri - } - - val name = createNodeRequest match { - case root: NodeCreatePayloadADM.RootNodeCreatePayloadADM => root.name - case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.name - } - - val position = createNodeRequest match { - case _: NodeCreatePayloadADM.RootNodeCreatePayloadADM => None - case child: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => child.position + val (id, parentNodeIri, projectIri, name, position) = createNodeRequest match { + case parent: NodeCreatePayloadADM.ListCreatePayloadADM => + (parent.id, None, parent.projectIri, parent.name, None) + case node: NodeCreatePayloadADM.ChildNodeCreatePayloadADM => + (node.id, node.parentNodeIri, node.projectIri, node.name, node.position) } def getPositionOfNewChild(children: Seq[ListChildNodeADM]): Int = { @@ -1001,7 +983,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde // Create the new list node depending on type createNewListSparqlString: String = createNodeRequest match { - case NodeCreatePayloadADM.RootNodeCreatePayloadADM( + case NodeCreatePayloadADM.ListCreatePayloadADM( _, projectIri, name, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 451b98a7d3..43ba964448 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -31,7 +31,7 @@ import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.LIST_CREATE_PERMISSION_ERROR import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ ChildNodeCreatePayloadADM, - RootNodeCreatePayloadADM + ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} @@ -140,7 +140,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) name = "body", value = "\"list\" item to create", required = true, - dataTypeClass = classOf[CreateListApiRequestADM], + dataTypeClass = classOf[CreateNodeApiRequestADM], paramType = "body" ), new ApiImplicitParam( @@ -187,7 +187,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val projectIri = stringFormatter .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) - val createRootNodePayloadADM: RootNodeCreatePayloadADM = RootNodeCreatePayloadADM( + val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( id, projectIri, name = maybeName, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index f9fdbc2a35..29c8855eeb 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -34,7 +34,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtil } import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ ChildNodeCreatePayloadADM, - RootNodeCreatePayloadADM + ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} @@ -124,7 +124,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) name = "body", value = "\"list\" to create", required = true, - dataTypeClass = classOf[CreateListApiRequestADM], + dataTypeClass = classOf[CreateNodeApiRequestADM], paramType = "body" ) ) @@ -151,7 +151,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val projectIri = stringFormatter .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) - val createRootNodePayloadADM: RootNodeCreatePayloadADM = RootNodeCreatePayloadADM( + val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( apiRequest.id, throw BadRequestException(s"Invalid custom node IRI") diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index e04f55c0b3..50852ea247 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -26,7 +26,7 @@ import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ ChildNodeCreatePayloadADM, - RootNodeCreatePayloadADM + ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} @@ -147,7 +147,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li converted.children should be(children) } - "throw 'BadRequestException' for `CreateListApiRequestADM` when project IRI is empty" in { + "throw 'BadRequestException' for `CreateNodeApiRequestADM` when project IRI is empty" in { val payload = s""" @@ -158,13 +158,13 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li |} """.stripMargin - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateListApiRequestADM] + val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] thrown.getMessage should equal(PROJECT_IRI_MISSING_ERROR) } - "throw 'BadRequestException' for `CreateListApiRequestADM` when project IRI is invalid" in { + "throw 'BadRequestException' for `CreateNodeApiRequestADM` when project IRI is invalid" in { val payload = s""" @@ -175,12 +175,12 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li |} """.stripMargin - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateListApiRequestADM] + val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] thrown.getMessage should equal(PROJECT_IRI_INVALID_ERROR) } - "throw 'BadRequestException' for `CreateListApiRequestADM` when labels is empty" in { + "throw 'BadRequestException' for `CreateNodeApiRequestADM` when labels is empty" in { val payload = s""" @@ -191,12 +191,12 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li |} """.stripMargin - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateListApiRequestADM] + val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] thrown.getMessage should equal(LABEL_MISSING_ERROR) } - "throw a 'BadRequestException' for `CreateListApiRequestADM` when an invalid list IRI is given" in { + "throw a 'BadRequestException' for `CreateNodeApiRequestADM` when an invalid list IRI is given" in { val payload = s""" @@ -208,12 +208,12 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li |} """.stripMargin - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateListApiRequestADM] + val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] thrown.getMessage should equal("Invalid list IRI") } - "throw 'BadRequestException' for `CreateListApiRequestADM` when value of a label is missing" in { + "throw 'BadRequestException' for `CreateNodeApiRequestADM` when value of a label is missing" in { val payload = s""" @@ -224,12 +224,12 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li |} """.stripMargin - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateListApiRequestADM] + val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] thrown.getMessage should equal("String value is missing.") } - "throw 'BadRequestException' for `CreateListApiRequestADM` when value of a comment is missing" in { + "throw 'BadRequestException' for `CreateNodeApiRequestADM` when value of a comment is missing" in { val payload = s""" @@ -241,7 +241,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li |} """.stripMargin - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateListApiRequestADM] + val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] thrown.getMessage should equal("String value is missing.") } diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index 8a7aa8ca26..dac69027ae 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -23,7 +23,7 @@ import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ ChildNodeCreatePayloadADM, - RootNodeCreatePayloadADM + ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages.{CreateNodeApiRequestADM, NodeCreatePayloadADM} import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 @@ -47,7 +47,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { */ private def createRootNodeCreatePayloadADM( createNodeApiRequestADM: CreateNodeApiRequestADM - ): RootNodeCreatePayloadADM = { + ): ListCreatePayloadADM = { val maybeName: Option[ListName] = createNodeApiRequestADM.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None @@ -58,7 +58,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { case None => None } - RootNodeCreatePayloadADM( + ListCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( createNodeApiRequestADM.id, throw BadRequestException(s"Invalid custom node IRI") @@ -75,7 +75,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } /** - * Convenience method returning the [[RootNodeCreatePayloadADM]] object + * Convenience method returning the [[ListCreatePayloadADM]] object * * @param id the optional custom IRI of the list node. * @param parentNodeIri the optional IRI of the parent node. @@ -84,7 +84,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { * @param position the optional position of the node. * @param labels labels of the list node. * @param comments comments of the list node. - * @return a [[RootNodeCreatePayloadADM]] + * @return a [[ListCreatePayloadADM]] */ private def createRootNodeApiRequestADM( id: Option[IRI] = None, @@ -96,18 +96,18 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { comments: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New comment", language = Some("en"))) ): CreateNodeApiRequestADM = CreateNodeApiRequestADM(id, parentNodeIri, projectIri, name, position, labels, comments) - "When the RootNodeCreatePayloadADM case class is created it" should { - "create a valid RootNodeCreatePayloadADM" in { + "When the ListCreatePayloadADM case class is created it" should { + "create a valid ListCreatePayloadADM" in { val request = createRootNodeApiRequestADM() - val rootNodeCreatePayloadADM = createRootNodeCreatePayloadADM(request) + val listCreatePayloadADM = createRootNodeCreatePayloadADM(request) - rootNodeCreatePayloadADM.id should equal(request.id) - rootNodeCreatePayloadADM.projectIri should equal(request.projectIri) - rootNodeCreatePayloadADM.name.map(_.value) should equal(request.name) - rootNodeCreatePayloadADM.labels.value should equal(request.labels) - rootNodeCreatePayloadADM.comments.value should equal(request.comments) + listCreatePayloadADM.id should equal(request.id) + listCreatePayloadADM.projectIri should equal(request.projectIri) + listCreatePayloadADM.name.map(_.value) should equal(request.name) + listCreatePayloadADM.labels.value should equal(request.labels) + listCreatePayloadADM.comments.value should equal(request.comments) val otherRequest = createRootNodeApiRequestADM( id = Some("http://rdfh.ch/lists/otherlistcustomid"), diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 05688a12ef..fdfc717104 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -28,7 +28,7 @@ import org.knora.webapi.exceptions.{BadRequestException, DuplicateValueException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ ChildNodeCreatePayloadADM, - RootNodeCreatePayloadADM + ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, StringLiteralV2} @@ -180,7 +180,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "used to modify lists" should { "create a list" in { responderManager ! ListCreateRequestADM( - createRootNode = RootNodeCreatePayloadADM( + createRootNode = ListCreatePayloadADM( projectIri = IMAGES_PROJECT_IRI, name = Some(ListName.create("neuelistename").fold(e => throw e, v => v)), labels = Labels @@ -221,7 +221,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val commentWithSpecialCharacter = "Neue \\\"Kommentar\\\"" val nameWithSpecialCharacter = "a new \\\"name\\\"" responderManager ! ListCreateRequestADM( - createRootNode = RootNodeCreatePayloadADM( + createRootNode = ListCreatePayloadADM( projectIri = IMAGES_PROJECT_IRI, name = Some(ListName.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), labels = Labels From 3579003763675795f56d238082f177f57f4aeee6 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 22 Oct 2021 13:26:26 +0200 Subject: [PATCH 18/32] fix test --- .../valueObjects/ListsValueObjectsADM.scala | 18 +++++++++++++++++- .../admin/ListsResponderADMSpec.scala | 4 +++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 324b3f45d1..e270a4de4e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -1,9 +1,25 @@ package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.exceptions.BadRequestException -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.INVALID_POSITION +import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ + INVALID_POSITION, + PROJECT_IRI_MISSING_ERROR +} import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 +/** + * ListName value object. + */ +sealed abstract case class ProjectIRI private (value: String) +object ProjectIRI { + def create(value: String): Either[Throwable, ProjectIRI] = + if (value.isEmpty) { + Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) + } else { + Right(new ProjectIRI(value) {}) + } +} + /** * ListName value object. */ diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index fdfc717104..51227ef0ee 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -520,7 +520,9 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with ) expectMsg( Failure( - BadRequestException(s"Invalid position given ${givenPosition.value}, maximum allowed position is = 2.") + BadRequestException( + s"Invalid position given ${givenPosition.map(_.value)}, maximum allowed position is = 2." + ) ) ) } From 47a75133743b108ff8c6befb62ebdc9307ff08b0 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 22 Oct 2021 14:18:45 +0200 Subject: [PATCH 19/32] add ProjectIRI value object --- .../listsmessages/ListPayloadsADM.scala | 8 +++--- .../listsmessages/ListsMessagesADM.scala | 2 +- .../valueObjects/ListsValueObjectsADM.scala | 13 +++++++--- .../responders/admin/ListsResponderADM.scala | 26 +++++++++---------- .../admin/lists/NewListsRouteADMFeature.scala | 24 +++++++---------- .../admin/lists/OldListsRouteADMFeature.scala | 21 ++++++++------- .../listsmessages/ListsMessagesADMSpec.scala | 7 +++-- .../ListsValueObjectsADMSpec.scala | 12 ++------- .../admin/ListsResponderADMSpec.scala | 21 ++++++++------- 9 files changed, 65 insertions(+), 69 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index 3e60801578..90128ffb12 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -1,7 +1,7 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} /** * List (parent node, former root node) and Node (former child node) creation payloads @@ -10,7 +10,7 @@ sealed trait NodeCreatePayloadADM object NodeCreatePayloadADM { final case class ListCreatePayloadADM( id: Option[IRI] = None, - projectIri: IRI, + projectIri: ProjectIRI, name: Option[ListName] = None, labels: Labels, comments: Comments @@ -18,7 +18,7 @@ object NodeCreatePayloadADM { final case class ChildNodeCreatePayloadADM( id: Option[IRI] = None, parentNodeIri: Option[IRI] = None, - projectIri: IRI, + projectIri: ProjectIRI, name: Option[ListName] = None, position: Option[Position] = None, labels: Labels, @@ -31,7 +31,7 @@ object NodeCreatePayloadADM { */ final case class NodeInfoChangePayloadADM( listIri: IRI, - projectIri: IRI, + projectIri: ProjectIRI, hasRootNode: Option[IRI] = None, position: Option[Position] = None, name: Option[ListName] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index ff111bd441..6e268a5818 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -67,7 +67,7 @@ case class CreateNodeApiRequestADM( // TODO: are below checks necessary anymore? CORRECT! but move all checks to value objects private val stringFormatter = StringFormatter.getInstanceForConstantOntologies - stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list node IRI")) + stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list IRI")) if (parentNodeIri.nonEmpty && !stringFormatter.isKnoraListIriStr(parentNodeIri.get)) { throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index e270a4de4e..df84af0164 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -1,6 +1,7 @@ package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ INVALID_POSITION, PROJECT_IRI_MISSING_ERROR @@ -8,15 +9,21 @@ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtil import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 /** - * ListName value object. + * ProjectIRI value object. */ sealed abstract case class ProjectIRI private (value: String) object ProjectIRI { + val stringFormatter = StringFormatter.getGeneralInstance + def create(value: String): Either[Throwable, ProjectIRI] = if (value.isEmpty) { Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) } else { - Right(new ProjectIRI(value) {}) + val validatedValue = stringFormatter.validateAndEscapeProjectIri( + value, + throw BadRequestException(s"Invalid project IRI") + ) + Right(new ProjectIRI(validatedValue) {}) } } @@ -27,7 +34,7 @@ sealed abstract case class ListName private (value: String) object ListName { def create(value: String): Either[Throwable, ListName] = if (value.isEmpty) { - Left(BadRequestException("Missing List Name")) + Left(BadRequestException("Missing list name")) } else { Right(new ListName(value) {}) } diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 5878344391..4e7e436bd7 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -40,7 +40,7 @@ import org.knora.webapi.messages.util.{KnoraSystemInstances, ResponderData} import org.knora.webapi.messages.{OntologyConstants, SmartIri} import org.knora.webapi.responders.Responder.handleUnexpectedMessage import org.knora.webapi.responders.{IriLocker, Responder} -import org.knora.webapi.messages.admin.responder.valueObjects.ListName +import org.knora.webapi.messages.admin.responder.valueObjects.{ListName, ProjectIRI} import scala.annotation.tailrec import scala.concurrent.Future @@ -937,7 +937,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde for { /* Verify that the project exists by retrieving it. We need the project information so that we can calculate the data graph and IRI for the new node. */ maybeProject <- (responderManager ? ProjectGetADM( - identifier = ProjectIdentifierADM(maybeIri = Some(projectIri)), + identifier = ProjectIdentifierADM(maybeIri = Some(projectIri.value)), featureFactoryConfig = featureFactoryConfig, KnoraSystemInstances.Users.SystemUser )).mapTo[Option[ProjectADM]] @@ -949,7 +949,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde /* verify that the list node name is unique for the project */ projectUniqueNodeName <- listNodeNameIsProjectUnique( - projectIri, + projectIri.value, name ) _ = if (!projectUniqueNodeName) { @@ -957,7 +957,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde val escapedName = name.get.value val unescapedName = stringFormatter.fromSparqlEncodedString(escapedName) throw BadRequestException( - s"The node name ${unescapedName} is already used by a list inside the project ${projectIri}." + s"The node name ${unescapedName} is already used by a list inside the project ${projectIri.value}." ) } @@ -995,7 +995,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde dataNamedGraph = dataNamedGraph, triplestore = settings.triplestoreType, listClassIri = OntologyConstants.KnoraBase.ListNode, - projectIri = projectIri, + projectIri = projectIri.value, nodeIri = newListNodeIri, parentNodeIri = None, rootNodeIri = rootNodeIri, @@ -1020,7 +1020,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde dataNamedGraph = dataNamedGraph, triplestore = settings.triplestoreType, listClassIri = OntologyConstants.KnoraBase.ListNode, - projectIri = projectIri, + projectIri = projectIri.value, nodeIri = newListNodeIri, parentNodeIri = parentNodeIri, rootNodeIri = rootNodeIri, @@ -1280,7 +1280,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde changeNodeNameSparqlString <- getUpdateNodeInfoSparqlStatement( changeNodeInfoRequest = NodeInfoChangePayloadADM( listIri = nodeIri, - projectIri = projectIri, + projectIri = ProjectIRI.create(projectIri).fold(e => throw e, v => v), name = Some(changeNodeNameRequest.name) ), featureFactoryConfig = featureFactoryConfig @@ -1366,7 +1366,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde changeNodeLabelsSparqlString <- getUpdateNodeInfoSparqlStatement( changeNodeInfoRequest = NodeInfoChangePayloadADM( listIri = nodeIri, - projectIri = projectIri, + projectIri = ProjectIRI.create(projectIri).fold(e => throw e, v => v), labels = Some(changeNodeLabelsRequest.labels) ), featureFactoryConfig = featureFactoryConfig @@ -1451,7 +1451,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde changeNodeCommentsSparqlString <- getUpdateNodeInfoSparqlStatement( changeNodeInfoRequest = NodeInfoChangePayloadADM( listIri = nodeIri, - projectIri = projectIri, + projectIri = ProjectIRI.create(projectIri).fold(e => throw e, v => v), comments = changeNodeCommentsRequest.comments ), featureFactoryConfig = featureFactoryConfig @@ -2168,16 +2168,16 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde ): Future[String] = for { // get the data graph of the project. - dataNamedGraph <- getDataNamedGraph(changeNodeInfoRequest.projectIri, featureFactoryConfig) + dataNamedGraph <- getDataNamedGraph(changeNodeInfoRequest.projectIri.value, featureFactoryConfig) /* verify that the list name is unique for the project */ nodeNameUnique: Boolean <- listNodeNameIsProjectUnique( - changeNodeInfoRequest.projectIri, + changeNodeInfoRequest.projectIri.value, changeNodeInfoRequest.name ) _ = if (!nodeNameUnique) { throw DuplicateValueException( - s"The name ${changeNodeInfoRequest.name.get} is already used by a list inside the project ${changeNodeInfoRequest.projectIri}." + s"The name ${changeNodeInfoRequest.name.get} is already used by a list inside the project ${changeNodeInfoRequest.projectIri.value}." ) } @@ -2210,7 +2210,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde hasOldName = hasOldName, isRootNode = isRootNode, maybeName = changeNodeInfoRequest.name.map(_.value), - projectIri = changeNodeInfoRequest.projectIri, + projectIri = changeNodeInfoRequest.projectIri.value, listClassIri = OntologyConstants.KnoraBase.ListNode, maybeLabels = changeNodeInfoRequest.labels.map(_.value), maybeComments = changeNodeInfoRequest.comments.map(_.value) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 43ba964448..acc4be6d41 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -34,7 +34,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -183,9 +183,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v) val comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) - - val projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( id, @@ -207,13 +205,10 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val requestMessage = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) - // check if the requesting user is allowed to perform operation - _ = println( - "77777", - requestingUser.permissions.isProjectAdmin(projectIri), - requestingUser.permissions.isSystemAdmin - ) - _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + + _ = if ( + !requestingUser.permissions.isProjectAdmin(projectIri.value) && !requestingUser.permissions.isSystemAdmin + ) { // not project or a system admin throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) } @@ -341,8 +336,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val listIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) - val projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val maybeName: Option[ListName] = apiRequest.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) @@ -380,7 +374,9 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val requestMessage: Future[NodeInfoChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) // check if the requesting user is allowed to perform operation - _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + _ = if ( + !requestingUser.permissions.isProjectAdmin(projectIri.value) && !requestingUser.permissions.isSystemAdmin + ) { // not project or a system admin throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 29c8855eeb..5723723878 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -37,7 +37,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -148,8 +148,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( id = stringFormatter.validateAndEscapeOptionalIri( @@ -171,7 +170,9 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) ) // check if the requesting user is allowed to perform operation - _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + _ = if ( + !requestingUser.permissions.isProjectAdmin(projectIri.value) && !requestingUser.permissions.isSystemAdmin + ) { // not project or a system admin throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) } @@ -284,8 +285,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, @@ -303,7 +303,9 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val requestMessage: Future[NodeInfoChangeRequestADM] = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) // check if the requesting user is allowed to perform operation - _ = if (!requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin) { + _ = if ( + !requestingUser.permissions.isProjectAdmin(projectIri.value) && !requestingUser.permissions.isSystemAdmin + ) { // not project or a system admin throw ForbiddenException(LIST_NODE_CREATE_PERMISSION_ERROR) } @@ -358,8 +360,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* add node to existing list node. the existing list node can be either the root or a child */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => - val projectIri = stringFormatter - .validateAndEscapeProjectIri(apiRequest.projectIri, throw BadRequestException(s"Invalid project IRI")) + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val maybeName: Option[ListName] = apiRequest.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) @@ -395,7 +396,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) // check if the requesting user is allowed to perform operation _ = if ( - !requestingUser.permissions.isProjectAdmin(projectIri) && !requestingUser.permissions.isSystemAdmin + !requestingUser.permissions.isProjectAdmin(projectIri.value) && !requestingUser.permissions.isSystemAdmin ) { // not project or a system admin throw ForbiddenException(LIST_CREATE_PERMISSION_ERROR) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index 50852ea247..c05c819737 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -28,9 +28,8 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload ChildNodeCreatePayloadADM, ListCreatePayloadADM } -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, Name, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ProjectIRI, Position} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} -import org.knora.webapi.sharedtestdata.SharedTestDataV1.IMAGES_PROJECT_IRI import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} import spray.json._ @@ -350,7 +349,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(exampleListIri), - projectIri = SharedTestDataADM.IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(SharedTestDataADM.IMAGES_PROJECT_IRI).fold(e => throw e, v => v), position = Some(Position.create(-3).fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New child node", language = Some("en")))) @@ -473,7 +472,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - thrown.getMessage should equal("Invalid list node IRI") + thrown.getMessage should equal("Invalid list IRI") } diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index dac69027ae..d8038cf0a3 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -63,11 +63,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { createNodeApiRequestADM.id, throw BadRequestException(s"Invalid custom node IRI") ), - projectIri = stringFormatter - .validateAndEscapeProjectIri( - createNodeApiRequestADM.projectIri, - throw BadRequestException(s"Invalid project IRI") - ), + projectIri = ProjectIRI.create(createNodeApiRequestADM.projectIri).fold(e => throw e, v => v), name = maybeName, labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), comments = Comments.create(createNodeApiRequestADM.comments).fold(e => throw e, v => v) @@ -168,11 +164,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { createNodeApiRequestADM.parentNodeIri, throw BadRequestException(s"Invalid parent node IRI") ), - projectIri = stringFormatter - .validateAndEscapeProjectIri( - createNodeApiRequestADM.projectIri, - throw BadRequestException(s"Invalid project IRI") - ), + projectIri = ProjectIRI.create(createNodeApiRequestADM.projectIri).fold(e => throw e, v => v), name = maybeName, position = maybePosition, labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 51227ef0ee..3c5e87c67d 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -35,7 +35,7 @@ import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, Strin import org.knora.webapi.sharedtestdata.SharedTestDataV1._ import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} import org.knora.webapi.util.MutableTestIri -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} import scala.concurrent.duration._ @@ -181,7 +181,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "create a list" in { responderManager ! ListCreateRequestADM( createRootNode = ListCreatePayloadADM( - projectIri = IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("neuelistename").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "Neue Liste", language = Some("de")))) @@ -222,7 +222,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val nameWithSpecialCharacter = "a new \\\"name\\\"" responderManager ! ListCreateRequestADM( createRootNode = ListCreatePayloadADM( - projectIri = IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create(nameWithSpecialCharacter).fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = labelWithSpecialCharacter, language = Some("de")))) @@ -263,7 +263,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with listIri = newListIri.get, changeNodeRequest = NodeInfoChangePayloadADM( listIri = newListIri.get, - projectIri = IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("updated name").fold(e => throw e, v => v)), labels = Some( Labels @@ -318,11 +318,12 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "not update basic list information if name is duplicate" in { val name = Some(ListName.create("sommer").fold(e => throw e, v => v)) + val projectIRI = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v) responderManager ! NodeInfoChangeRequestADM( listIri = newListIri.get, changeNodeRequest = NodeInfoChangePayloadADM( listIri = newListIri.get, - projectIri = IMAGES_PROJECT_IRI, + projectIri = projectIRI, name = name ), featureFactoryConfig = defaultFeatureFactoryConfig, @@ -332,7 +333,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with expectMsg( Failure( DuplicateValueException( - s"The name ${name.value} is already used by a list inside the project http://rdfh.ch/projects/00FF." + s"The name ${name.value} is already used by a list inside the project ${projectIRI.value}." ) ) ) @@ -342,7 +343,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("first").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New First Child List Node Value", language = Some("en")))) @@ -396,7 +397,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("second").fold(e => throw e, v => v)), position = Some(Position.create(0).fold(e => throw e, v => v)), labels = Labels @@ -449,7 +450,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(secondChildIri.get), - projectIri = IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("third").fold(e => throw e, v => v)), labels = Labels .create(Seq(StringLiteralV2(value = "New Third Child List Node Value", language = Some("en")))) @@ -502,7 +503,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( parentNodeIri = Some(newListIri.get), - projectIri = IMAGES_PROJECT_IRI, + projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("fourth").fold(e => throw e, v => v)), position = givenPosition, labels = Labels From 3aad90ac277a0236d09e2937f2f3477b4588c9d5 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 22 Oct 2021 15:32:01 +0200 Subject: [PATCH 20/32] add CustomID value object --- .../listsmessages/ListPayloadsADM.scala | 13 +++++-- .../valueObjects/ListsValueObjectsADM.scala | 37 +++++++++++++++---- .../responders/admin/ListsResponderADM.scala | 2 +- .../admin/lists/NewListsRouteADMFeature.scala | 21 +++++++---- .../admin/lists/OldListsRouteADMFeature.scala | 29 ++++++++++----- .../ListsValueObjectsADMSpec.scala | 28 ++++++-------- 6 files changed, 85 insertions(+), 45 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index 90128ffb12..ac0a63807d 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -1,7 +1,14 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Comments, + CustomID, + Labels, + ListName, + Position, + ProjectIRI +} /** * List (parent node, former root node) and Node (former child node) creation payloads @@ -9,14 +16,14 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, sealed trait NodeCreatePayloadADM object NodeCreatePayloadADM { final case class ListCreatePayloadADM( - id: Option[IRI] = None, + id: Option[CustomID] = None, projectIri: ProjectIRI, name: Option[ListName] = None, labels: Labels, comments: Comments ) extends NodeCreatePayloadADM final case class ChildNodeCreatePayloadADM( - id: Option[IRI] = None, + id: Option[CustomID] = None, parentNodeIri: Option[IRI] = None, projectIri: ProjectIRI, name: Option[ListName] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index df84af0164..3ccdd7380d 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -1,34 +1,55 @@ package org.knora.webapi.messages.admin.responder.valueObjects +import org.knora.webapi.IRI import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ INVALID_POSITION, + PROJECT_IRI_INVALID_ERROR, PROJECT_IRI_MISSING_ERROR } import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 /** - * ProjectIRI value object. + * List CustomID value object. */ -sealed abstract case class ProjectIRI private (value: String) +sealed abstract case class CustomID private (value: IRI) +object CustomID { + val stringFormatter = StringFormatter.getGeneralInstance + + def create(value: IRI): Either[Throwable, CustomID] = + if (value.isEmpty) { + Left(BadRequestException("Invalid custom node IRI")) + } else { + val validatedValue = stringFormatter.validateAndEscapeIri( + value, + throw BadRequestException(s"Invalid custom node IRI") + ) + Right(new CustomID(validatedValue) {}) + } +} + +/** + * List ProjectIRI value object. + */ +sealed abstract case class ProjectIRI private (value: IRI) object ProjectIRI { val stringFormatter = StringFormatter.getGeneralInstance - def create(value: String): Either[Throwable, ProjectIRI] = + def create(value: IRI): Either[Throwable, ProjectIRI] = if (value.isEmpty) { Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) } else { val validatedValue = stringFormatter.validateAndEscapeProjectIri( value, - throw BadRequestException(s"Invalid project IRI") + throw BadRequestException(PROJECT_IRI_INVALID_ERROR) ) Right(new ProjectIRI(validatedValue) {}) } } /** - * ListName value object. + * List ListName value object. */ sealed abstract case class ListName private (value: String) object ListName { @@ -41,7 +62,7 @@ object ListName { } /** - * Position value object. + * List Position value object. */ sealed abstract case class Position private (value: Int) object Position { @@ -54,7 +75,7 @@ object Position { } /** - * Labels value object. + * List Labels value object. */ sealed abstract case class Labels private (value: Seq[StringLiteralV2]) object Labels { @@ -67,7 +88,7 @@ object Labels { } /** - * Comments value object. + * List Comments value object. */ sealed abstract case class Comments private (value: Seq[StringLiteralV2]) object Comments { diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 4e7e436bd7..86e15990aa 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -977,7 +977,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } // check the custom IRI; if not given, create an unused IRI - customListIri: Option[SmartIri] = id.map(iri => iri.toSmartIri) + customListIri: Option[SmartIri] = id.map(_.value).map(_.toSmartIri) maybeShortcode: String = project.shortcode newListNodeIri: IRI <- checkOrCreateEntityIri(customListIri, stringFormatter.makeRandomListIri(maybeShortcode)) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index acc4be6d41..7e27661aaf 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -34,7 +34,14 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Comments, + CustomID, + Labels, + ListName, + Position, + ProjectIRI +} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -161,10 +168,10 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list item (root or child node) */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => - val id = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.id, - throw BadRequestException(s"Invalid custom node IRI") - ) + val maybeId: Option[CustomID] = apiRequest.id match { + case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) + case None => None + } val parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( apiRequest.parentNodeIri, @@ -186,7 +193,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( - id, + id = maybeId, projectIri, name = maybeName, labels, @@ -194,7 +201,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) ) val createChildNodePayloadADM: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( - id, + id = maybeId, parentNodeIri, projectIri, name = maybeName, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 5723723878..20231ea712 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -37,7 +37,14 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload ListCreatePayloadADM } import org.knora.webapi.messages.admin.responder.listsmessages._ -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Comments, + CustomID, + Labels, + ListName, + Position, + ProjectIRI +} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import scala.concurrent.Future @@ -138,6 +145,11 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => + val maybeId: Option[CustomID] = apiRequest.id match { + case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) + case None => None + } + val maybeName: Option[ListName] = apiRequest.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None @@ -151,10 +163,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( - id = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.id, - throw BadRequestException(s"Invalid custom node IRI") - ), + id = maybeId, projectIri, name = maybeName, labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), @@ -360,6 +369,11 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* add node to existing list node. the existing list node can be either the root or a child */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => + val maybeId: Option[CustomID] = apiRequest.id match { + case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) + case None => None + } + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val maybeName: Option[ListName] = apiRequest.name match { @@ -373,10 +387,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) } val createChildNodeRequest: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( - id = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.id, - throw BadRequestException(s"Invalid custom node IRI") - ), + id = maybeId, parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( apiRequest.parentNodeIri, throw BadRequestException(s"Invalid parent node IRI") diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index d8038cf0a3..c2ecd29444 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -48,21 +48,18 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { private def createRootNodeCreatePayloadADM( createNodeApiRequestADM: CreateNodeApiRequestADM ): ListCreatePayloadADM = { - val maybeName: Option[ListName] = createNodeApiRequestADM.name match { - case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) + val maybeId: Option[CustomID] = createNodeApiRequestADM.id match { + case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) case None => None } - val maybePosition: Option[Position] = createNodeApiRequestADM.position match { - case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) + val maybeName: Option[ListName] = createNodeApiRequestADM.name match { + case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None } ListCreatePayloadADM( - id = stringFormatter.validateAndEscapeOptionalIri( - createNodeApiRequestADM.id, - throw BadRequestException(s"Invalid custom node IRI") - ), + id = maybeId, projectIri = ProjectIRI.create(createNodeApiRequestADM.projectIri).fold(e => throw e, v => v), name = maybeName, labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), @@ -140,6 +137,11 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { private def createChildNodeCreatePayloadADM( createNodeApiRequestADM: CreateNodeApiRequestADM ): ChildNodeCreatePayloadADM = { + val maybeId: Option[CustomID] = createNodeApiRequestADM.id match { + case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) + case None => None + } + val maybeName: Option[ListName] = createNodeApiRequestADM.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None @@ -150,16 +152,8 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { case None => None } -// val maybeComments: Option[Comments] = createNodeApiRequestADM.comments match { -// case Some(value) => Some(Comments.create(value).fold(e => throw e, v => v)) -// case None => None -// } - ChildNodeCreatePayloadADM( - id = stringFormatter.validateAndEscapeOptionalIri( - createNodeApiRequestADM.id, - throw BadRequestException(s"Invalid custom node IRI") - ), + id = maybeId, parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( createNodeApiRequestADM.parentNodeIri, throw BadRequestException(s"Invalid parent node IRI") From 983f3964e12361660f0dcdf5ae486f9cd410cf78 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 22 Oct 2021 16:18:24 +0200 Subject: [PATCH 21/32] add ListIRI value object --- .../listsmessages/ListPayloadsADM.scala | 5 +-- .../valueObjects/ListsValueObjectsADM.scala | 32 ++++++++++++++++--- .../responders/admin/ListsResponderADM.scala | 16 +++++----- .../admin/lists/NewListsRouteADMFeature.scala | 17 +++++----- .../admin/lists/OldListsRouteADMFeature.scala | 19 +++++------ .../listsmessages/ListsMessagesADMSpec.scala | 4 +-- .../ListsValueObjectsADMSpec.scala | 30 +++++++++-------- .../admin/ListsResponderADMSpec.scala | 21 ++++++++---- 8 files changed, 89 insertions(+), 55 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index ac0a63807d..e3ad480c8a 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -5,6 +5,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ Comments, CustomID, Labels, + ListIRI, ListName, Position, ProjectIRI @@ -24,7 +25,7 @@ object NodeCreatePayloadADM { ) extends NodeCreatePayloadADM final case class ChildNodeCreatePayloadADM( id: Option[CustomID] = None, - parentNodeIri: Option[IRI] = None, + parentNodeIri: Option[ListIRI] = None, projectIri: ProjectIRI, name: Option[ListName] = None, position: Option[Position] = None, @@ -37,7 +38,7 @@ object NodeCreatePayloadADM { * Node Info update payload */ final case class NodeInfoChangePayloadADM( - listIri: IRI, + listIri: ListIRI, projectIri: ProjectIRI, hasRootNode: Option[IRI] = None, position: Option[Position] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 3ccdd7380d..f15c4d34b3 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -5,20 +5,44 @@ import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ INVALID_POSITION, + LIST_NODE_IRI_INVALID_ERROR, + LIST_NODE_IRI_MISSING_ERROR, PROJECT_IRI_INVALID_ERROR, PROJECT_IRI_MISSING_ERROR } import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 +//TODO: sprawdzic na koncu wszystkie czeki w messangerze czy poktrywaja sie tu i tak samo tresci bledow +//TODO: possible to somehow merge all IRI related value objects? what about diff exception messages + +/** + * List ListIRI value object. + */ +sealed abstract case class ListIRI private (value: String) +object ListIRI { + val stringFormatter = StringFormatter.getGeneralInstance + + def create(value: String): Either[Throwable, ListIRI] = + if (value.isEmpty) { + Left(BadRequestException(LIST_NODE_IRI_MISSING_ERROR)) + } else { + val validatedValue = stringFormatter.validateAndEscapeIri( + value, + throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR) + ) + Right(new ListIRI(validatedValue) {}) + } +} /** * List CustomID value object. */ -sealed abstract case class CustomID private (value: IRI) +sealed abstract case class CustomID private (value: String) object CustomID { val stringFormatter = StringFormatter.getGeneralInstance - def create(value: IRI): Either[Throwable, CustomID] = + def create(value: String): Either[Throwable, CustomID] = if (value.isEmpty) { +// TODO: if id i only optional empty condition shouldn't exist Left(BadRequestException("Invalid custom node IRI")) } else { val validatedValue = stringFormatter.validateAndEscapeIri( @@ -32,11 +56,11 @@ object CustomID { /** * List ProjectIRI value object. */ -sealed abstract case class ProjectIRI private (value: IRI) +sealed abstract case class ProjectIRI private (value: String) object ProjectIRI { val stringFormatter = StringFormatter.getGeneralInstance - def create(value: IRI): Either[Throwable, ProjectIRI] = + def create(value: String): Either[Throwable, ProjectIRI] = if (value.isEmpty) { Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) } else { diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 86e15990aa..958f5fbdc3 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -40,7 +40,7 @@ import org.knora.webapi.messages.util.{KnoraSystemInstances, ResponderData} import org.knora.webapi.messages.{OntologyConstants, SmartIri} import org.knora.webapi.responders.Responder.handleUnexpectedMessage import org.knora.webapi.responders.{IriLocker, Responder} -import org.knora.webapi.messages.admin.responder.valueObjects.{ListName, ProjectIRI} +import org.knora.webapi.messages.admin.responder.valueObjects.{ListIRI, ListName, ProjectIRI} import scala.annotation.tailrec import scala.concurrent.Future @@ -968,7 +968,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde (newPosition: Option[Int], rootNodeIri: Option[IRI]) <- if (parentNodeIri.nonEmpty) { getRootNodeAndPositionOfNewChild( - parentNodeIri = parentNodeIri.get, + parentNodeIri = parentNodeIri.get.value, dataNamedGraph = dataNamedGraph, featureFactoryConfig = featureFactoryConfig ) @@ -1022,7 +1022,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde listClassIri = OntologyConstants.KnoraBase.ListNode, projectIri = projectIri.value, nodeIri = newListNodeIri, - parentNodeIri = parentNodeIri, + parentNodeIri = parentNodeIri.map(_.value), rootNodeIri = rootNodeIri, position = newPosition, maybeName = name.map(_.value), @@ -1279,7 +1279,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde changeNodeNameSparqlString <- getUpdateNodeInfoSparqlStatement( changeNodeInfoRequest = NodeInfoChangePayloadADM( - listIri = nodeIri, + listIri = ListIRI.create(nodeIri).fold(e => throw e, v => v), projectIri = ProjectIRI.create(projectIri).fold(e => throw e, v => v), name = Some(changeNodeNameRequest.name) ), @@ -1365,7 +1365,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde } changeNodeLabelsSparqlString <- getUpdateNodeInfoSparqlStatement( changeNodeInfoRequest = NodeInfoChangePayloadADM( - listIri = nodeIri, + listIri = ListIRI.create(nodeIri).fold(e => throw e, v => v), projectIri = ProjectIRI.create(projectIri).fold(e => throw e, v => v), labels = Some(changeNodeLabelsRequest.labels) ), @@ -1450,7 +1450,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde changeNodeCommentsSparqlString <- getUpdateNodeInfoSparqlStatement( changeNodeInfoRequest = NodeInfoChangePayloadADM( - listIri = nodeIri, + listIri = ListIRI.create(nodeIri).fold(e => throw e, v => v), projectIri = ProjectIRI.create(projectIri).fold(e => throw e, v => v), comments = changeNodeCommentsRequest.comments ), @@ -2183,7 +2183,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde /* Verify that the node with Iri exists. */ maybeNode <- listNodeGetADM( - nodeIri = changeNodeInfoRequest.listIri, + nodeIri = changeNodeInfoRequest.listIri.value, shallow = true, featureFactoryConfig = featureFactoryConfig, requestingUser = KnoraSystemInstances.Users.SystemUser @@ -2206,7 +2206,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde .updateListInfo( dataNamedGraph = dataNamedGraph, triplestore = settings.triplestoreType, - nodeIri = changeNodeInfoRequest.listIri, + nodeIri = changeNodeInfoRequest.listIri.value, hasOldName = hasOldName, isRootNode = isRootNode, maybeName = changeNodeInfoRequest.name.map(_.value), diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 7e27661aaf..8000bd2142 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -38,6 +38,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ Comments, CustomID, Labels, + ListIRI, ListName, Position, ProjectIRI @@ -173,10 +174,10 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.parentNodeIri, - throw BadRequestException(s"Invalid parent node IRI") - ) + val maybeParentNodeIri: Option[ListIRI] = apiRequest.parentNodeIri match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) + case None => None + } val maybeName: Option[ListName] = apiRequest.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) @@ -202,7 +203,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val createChildNodePayloadADM: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( id = maybeId, - parentNodeIri, + parentNodeIri = maybeParentNodeIri, projectIri, name = maybeName, position = maybePosition, @@ -340,9 +341,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) put { /* update existing list node (either root or child) */ entity(as[ChangeNodeInfoApiRequestADM]) { apiRequest => requestContext => - val listIri = - stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) - + val listIri = ListIRI.create(apiRequest.listIri).fold(e => throw e, v => v) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val maybeName: Option[ListName] = apiRequest.name match { @@ -389,7 +388,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) } } yield NodeInfoChangeRequestADM( //TODO: why "listIri" property is doubled - here and inside "changeNodeRequest" - listIri = listIri, + listIri = listIri.value, changeNodeRequest = changeNodeInfoPayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 20231ea712..05f71ce895 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -41,6 +41,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ Comments, CustomID, Labels, + ListIRI, ListName, Position, ProjectIRI @@ -271,8 +272,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) put { /* update existing list node (either root or child) */ entity(as[ChangeNodeInfoApiRequestADM]) { apiRequest => requestContext => - val listIri = - stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) + val listIri = ListIRI.create(apiRequest.listIri).fold(e => throw e, v => v) + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val maybeName: Option[ListName] = apiRequest.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) @@ -294,8 +295,6 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) - val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, projectIri, @@ -319,7 +318,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) throw ForbiddenException(LIST_NODE_CREATE_PERMISSION_ERROR) } } yield NodeInfoChangeRequestADM( - listIri = listIri, + listIri = listIri.value, changeNodeRequest = changeNodeInfoPayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, @@ -374,6 +373,11 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } + val maybeParentNodeIri: Option[ListIRI] = apiRequest.parentNodeIri match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) + case None => None + } + val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val maybeName: Option[ListName] = apiRequest.name match { @@ -388,10 +392,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val createChildNodeRequest: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( id = maybeId, - parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.parentNodeIri, - throw BadRequestException(s"Invalid parent node IRI") - ), + parentNodeIri = maybeParentNodeIri, projectIri, name = maybeName, position = maybePosition, diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index c05c819737..d2d42511aa 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -28,7 +28,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload ChildNodeCreatePayloadADM, ListCreatePayloadADM } -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ProjectIRI, Position} +import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListIRI, ProjectIRI, Position} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} import spray.json._ @@ -348,7 +348,7 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li val caught = intercept[BadRequestException]( ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( - parentNodeIri = Some(exampleListIri), + parentNodeIri = Some(ListIRI.create(exampleListIri).fold(e => throw e, v => v)), projectIri = ProjectIRI.create(SharedTestDataADM.IMAGES_PROJECT_IRI).fold(e => throw e, v => v), position = Some(Position.create(-3).fold(e => throw e, v => v)), labels = Labels diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index c2ecd29444..71d1f08bd2 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -97,7 +97,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { val listCreatePayloadADM = createRootNodeCreatePayloadADM(request) listCreatePayloadADM.id should equal(request.id) - listCreatePayloadADM.projectIri should equal(request.projectIri) + listCreatePayloadADM.projectIri.value should equal(request.projectIri) listCreatePayloadADM.name.map(_.value) should equal(request.name) listCreatePayloadADM.labels.value should equal(request.labels) listCreatePayloadADM.comments.value should equal(request.comments) @@ -114,14 +114,14 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { val otherRootNodeCreatePayloadADM = createRootNodeCreatePayloadADM(otherRequest) - otherRootNodeCreatePayloadADM.id should equal(otherRequest.id) - otherRootNodeCreatePayloadADM.projectIri should equal(otherRequest.projectIri) + otherRootNodeCreatePayloadADM.id.map(_.value) should equal(otherRequest.id) + otherRootNodeCreatePayloadADM.projectIri.value should equal(otherRequest.projectIri) otherRootNodeCreatePayloadADM.name.map(_.value) should equal(otherRequest.name) otherRootNodeCreatePayloadADM.labels.value should equal(otherRequest.labels) otherRootNodeCreatePayloadADM.comments.value should equal(otherRequest.comments) - otherRootNodeCreatePayloadADM.id should not equal request.id - otherRootNodeCreatePayloadADM.projectIri should not equal request.projectIri + otherRootNodeCreatePayloadADM.id.map(_.value) should not equal request.id + otherRootNodeCreatePayloadADM.projectIri.value should not equal request.projectIri otherRootNodeCreatePayloadADM.name.get.value should not equal request.name otherRootNodeCreatePayloadADM.labels.value should not equal request.labels otherRootNodeCreatePayloadADM.comments.value should not equal request.comments @@ -142,6 +142,11 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { case None => None } + val maybeParentNodeIri: Option[ListIRI] = createNodeApiRequestADM.parentNodeIri match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) + case None => None + } + val maybeName: Option[ListName] = createNodeApiRequestADM.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None @@ -154,10 +159,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { ChildNodeCreatePayloadADM( id = maybeId, - parentNodeIri = stringFormatter.validateAndEscapeOptionalIri( - createNodeApiRequestADM.parentNodeIri, - throw BadRequestException(s"Invalid parent node IRI") - ), + parentNodeIri = maybeParentNodeIri, projectIri = ProjectIRI.create(createNodeApiRequestADM.projectIri).fold(e => throw e, v => v), name = maybeName, position = maybePosition, @@ -198,7 +200,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { childNodeCreatePayloadADM.id should equal(request.id) childNodeCreatePayloadADM.parentNodeIri should equal(request.parentNodeIri) - childNodeCreatePayloadADM.projectIri should equal(request.projectIri) + childNodeCreatePayloadADM.projectIri.value should equal(request.projectIri) childNodeCreatePayloadADM.name.map(_.value) should equal(request.name) childNodeCreatePayloadADM.position.map(_.value) should equal(request.position) childNodeCreatePayloadADM.labels.value should equal(request.labels) @@ -217,18 +219,18 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { val otherChildNodeCreatePayloadADM = createChildNodeCreatePayloadADM(otherRequest) - otherChildNodeCreatePayloadADM.id should equal(otherRequest.id) + otherChildNodeCreatePayloadADM.id.map(_.value) should equal(otherRequest.id) otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) - otherChildNodeCreatePayloadADM.projectIri should equal(otherRequest.projectIri) + otherChildNodeCreatePayloadADM.projectIri.value should equal(otherRequest.projectIri) otherChildNodeCreatePayloadADM.name.map(_.value) should equal(otherRequest.name) otherChildNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) otherChildNodeCreatePayloadADM.labels.value should equal(otherRequest.labels) // TODO: bring below back after separating ChildNodeCreateApiRequestADM from CreateNodeApiRequestADM // otherChildNodeCreatePayloadADM.comments.map(_.value) should equal(otherRequest.comments) - otherChildNodeCreatePayloadADM.id should not equal request.id + otherChildNodeCreatePayloadADM.id.map(_.value) should not equal request.id // otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) - otherChildNodeCreatePayloadADM.projectIri should not equal request.projectIri + otherChildNodeCreatePayloadADM.projectIri.value should not equal request.projectIri otherChildNodeCreatePayloadADM.name.get.value should not equal request.name // otherChildNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) otherChildNodeCreatePayloadADM.labels.value should not equal request.labels diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index 3c5e87c67d..b3d8afa485 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -35,7 +35,14 @@ import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, Strin import org.knora.webapi.sharedtestdata.SharedTestDataV1._ import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} import org.knora.webapi.util.MutableTestIri -import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListName, Position, ProjectIRI} +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Comments, + Labels, + ListIRI, + ListName, + Position, + ProjectIRI +} import scala.concurrent.duration._ @@ -262,7 +269,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val changeNodeInfoRequest = NodeInfoChangeRequestADM( listIri = newListIri.get, changeNodeRequest = NodeInfoChangePayloadADM( - listIri = newListIri.get, + listIri = ListIRI.create(newListIri.get).fold(e => throw e, v => v), projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("updated name").fold(e => throw e, v => v)), labels = Some( @@ -322,7 +329,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with responderManager ! NodeInfoChangeRequestADM( listIri = newListIri.get, changeNodeRequest = NodeInfoChangePayloadADM( - listIri = newListIri.get, + listIri = ListIRI.create(newListIri.get).fold(e => throw e, v => v), projectIri = projectIRI, name = name ), @@ -342,7 +349,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to list - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( - parentNodeIri = Some(newListIri.get), + parentNodeIri = Some(ListIRI.create(newListIri.get).fold(e => throw e, v => v)), projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("first").fold(e => throw e, v => v)), labels = Labels @@ -396,7 +403,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add second child to list in first position - to the root node" in { responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( - parentNodeIri = Some(newListIri.get), + parentNodeIri = Some(ListIRI.create(newListIri.get).fold(e => throw e, v => v)), projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("second").fold(e => throw e, v => v)), position = Some(Position.create(0).fold(e => throw e, v => v)), @@ -449,7 +456,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with "add child to second child node" in { responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( - parentNodeIri = Some(secondChildIri.get), + parentNodeIri = Some(ListIRI.create(secondChildIri.get).fold(e => throw e, v => v)), projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("third").fold(e => throw e, v => v)), labels = Labels @@ -502,7 +509,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val givenPosition = Some(Position.create(20).fold(e => throw e, v => v)) responderManager ! ListChildNodeCreateRequestADM( createChildNodeRequest = ChildNodeCreatePayloadADM( - parentNodeIri = Some(newListIri.get), + parentNodeIri = Some(ListIRI.create(newListIri.get).fold(e => throw e, v => v)), projectIri = ProjectIRI.create(IMAGES_PROJECT_IRI).fold(e => throw e, v => v), name = Some(ListName.create("fourth").fold(e => throw e, v => v)), position = givenPosition, From c8abba67526c1353c25b16749840366a92e02a3b Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 22 Oct 2021 16:27:26 +0200 Subject: [PATCH 22/32] add RootNodeIRI value object --- .../listsmessages/ListPayloadsADM.scala | 5 ++-- .../valueObjects/ListsValueObjectsADM.scala | 24 +++++++++++++++++++ .../admin/lists/NewListsRouteADMFeature.scala | 13 ++++++---- .../admin/lists/OldListsRouteADMFeature.scala | 13 ++++++---- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index e3ad480c8a..b703648270 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -8,7 +8,8 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ ListIRI, ListName, Position, - ProjectIRI + ProjectIRI, + RootNodeIRI } /** @@ -40,7 +41,7 @@ object NodeCreatePayloadADM { final case class NodeInfoChangePayloadADM( listIri: ListIRI, projectIri: ProjectIRI, - hasRootNode: Option[IRI] = None, + hasRootNode: Option[RootNodeIRI] = None, position: Option[Position] = None, name: Option[ListName] = None, labels: Option[Labels] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index f15c4d34b3..2c134eab66 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -13,6 +13,10 @@ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtil import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 //TODO: sprawdzic na koncu wszystkie czeki w messangerze czy poktrywaja sie tu i tak samo tresci bledow //TODO: possible to somehow merge all IRI related value objects? what about diff exception messages +// either use below checks in route to throw custom exceptions for one IRI value object +// or bring these matches here +//case Some(value) => Some(Comments.create(value).fold(e => throw e, v => v)) +//case None => None /** * List ListIRI value object. @@ -72,6 +76,26 @@ object ProjectIRI { } } +/** + * List RootNodeIRI value object. + */ +sealed abstract case class RootNodeIRI private (value: String) +object RootNodeIRI { + val stringFormatter = StringFormatter.getGeneralInstance + + def create(value: String): Either[Throwable, RootNodeIRI] = + // TODO: if id i only optional empty condition shouldn't exist + if (value.isEmpty) { + Left(BadRequestException(s"Missing root node IRI")) + } else { + val validatedValue = stringFormatter.validateAndEscapeIri( + value, + throw BadRequestException(s"Invalid root node IRI") + ) + Right(new RootNodeIRI(validatedValue) {}) + } +} + /** * List ListName value object. */ diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 8000bd2142..3b8422e600 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -41,7 +41,8 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ ListIRI, ListName, Position, - ProjectIRI + ProjectIRI, + RootNodeIRI } import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} @@ -344,6 +345,11 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val listIri = ListIRI.create(apiRequest.listIri).fold(e => throw e, v => v) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) + val maybeHasRootNode: Option[RootNodeIRI] = apiRequest.hasRootNode match { + case Some(value) => Some(RootNodeIRI.create(value).fold(e => throw e, v => v)) + case None => None + } + val maybeName: Option[ListName] = apiRequest.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None @@ -367,10 +373,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, projectIri, - hasRootNode = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.hasRootNode, - throw BadRequestException(s"Invalid root node IRI") - ), + hasRootNode = maybeHasRootNode, position = maybePosition, name = maybeName, labels = maybeLabels, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 05f71ce895..0225401039 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -44,7 +44,8 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ ListIRI, ListName, Position, - ProjectIRI + ProjectIRI, + RootNodeIRI } import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} @@ -275,6 +276,11 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val listIri = ListIRI.create(apiRequest.listIri).fold(e => throw e, v => v) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) + val maybeHasRootNode: Option[RootNodeIRI] = apiRequest.hasRootNode match { + case Some(value) => Some(RootNodeIRI.create(value).fold(e => throw e, v => v)) + case None => None + } + val maybeName: Option[ListName] = apiRequest.name match { case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) case None => None @@ -298,10 +304,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val changeNodeInfoPayloadADM: NodeInfoChangePayloadADM = NodeInfoChangePayloadADM( listIri, projectIri, - hasRootNode = stringFormatter.validateAndEscapeOptionalIri( - apiRequest.hasRootNode, - throw BadRequestException(s"Invalid root node IRI") - ), + hasRootNode = maybeHasRootNode, position = maybePosition, name = maybeName, labels = maybeLabels, From 40a0938adfa1f37d379d419bfbd86759ab2217f3 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Mon, 25 Oct 2021 14:32:45 +0200 Subject: [PATCH 23/32] fix tests --- .../responder/valueObjects/ListsValueObjectsADM.scala | 7 ++++--- .../knora/webapi/responders/admin/ListsResponderADM.scala | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 2c134eab66..1265035109 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -5,6 +5,7 @@ import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ INVALID_POSITION, + LABEL_MISSING_ERROR, LIST_NODE_IRI_INVALID_ERROR, LIST_NODE_IRI_MISSING_ERROR, PROJECT_IRI_INVALID_ERROR, @@ -46,7 +47,7 @@ object CustomID { def create(value: String): Either[Throwable, CustomID] = if (value.isEmpty) { -// TODO: if id i only optional empty condition shouldn't exist +// TODO: if id is only optional empty condition shouldn't exist Left(BadRequestException("Invalid custom node IRI")) } else { val validatedValue = stringFormatter.validateAndEscapeIri( @@ -84,7 +85,7 @@ object RootNodeIRI { val stringFormatter = StringFormatter.getGeneralInstance def create(value: String): Either[Throwable, RootNodeIRI] = - // TODO: if id i only optional empty condition shouldn't exist + // TODO: if id is only optional empty condition shouldn't exist if (value.isEmpty) { Left(BadRequestException(s"Missing root node IRI")) } else { @@ -129,7 +130,7 @@ sealed abstract case class Labels private (value: Seq[StringLiteralV2]) object Labels { def create(value: Seq[StringLiteralV2]): Either[Throwable, Labels] = if (value.isEmpty) { - Left(BadRequestException("Missing labels")) + Left(BadRequestException(LABEL_MISSING_ERROR)) } else { Right(new Labels(value) {}) } diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 958f5fbdc3..d2d1efe2ec 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -1138,9 +1138,11 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde ): Future[NodeInfoGetResponseADM] = for { + _ <- Future(println("77777", nodeIri, changeNodeRequest.listIri)) + // check if nodeIRI in path and payload match _ <- Future( - if (!nodeIri.equals(changeNodeRequest.listIri)) + if (!nodeIri.equals(changeNodeRequest.listIri.value)) throw BadRequestException("IRI in path and payload don't match.") ) From 2b5b607c31ce9658c2fe70351f246b41f21be744 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Tue, 26 Oct 2021 17:38:18 +0200 Subject: [PATCH 24/32] update value objects + add unit tests --- .../listsmessages/ListPayloadsADM.scala | 5 +- .../listsmessages/ListsMessagesADM.scala | 86 ++--- .../listsmessages/ListsMessagesUtilADM.scala | 2 + .../valueObjects/ListsValueObjectsADM.scala | 65 ++-- .../admin/lists/NewListsRouteADMFeature.scala | 5 +- .../admin/lists/OldListsRouteADMFeature.scala | 9 +- .../ListsValueObjectsADMSpec.scala | 302 +++++++----------- 7 files changed, 196 insertions(+), 278 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index b703648270..b310a6f08e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -3,7 +3,6 @@ package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.valueObjects.{ Comments, - CustomID, Labels, ListIRI, ListName, @@ -18,14 +17,14 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ sealed trait NodeCreatePayloadADM object NodeCreatePayloadADM { final case class ListCreatePayloadADM( - id: Option[CustomID] = None, + id: Option[ListIRI] = None, projectIri: ProjectIRI, name: Option[ListName] = None, labels: Labels, comments: Comments ) extends NodeCreatePayloadADM final case class ChildNodeCreatePayloadADM( - id: Option[CustomID] = None, + id: Option[ListIRI] = None, parentNodeIri: Option[ListIRI] = None, projectIri: ProjectIRI, name: Option[ListName] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 6e268a5818..728c4cbdd7 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -66,55 +66,55 @@ case class CreateNodeApiRequestADM( ) extends ListADMJsonProtocol { // TODO: are below checks necessary anymore? CORRECT! but move all checks to value objects - private val stringFormatter = StringFormatter.getInstanceForConstantOntologies - stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list IRI")) - - if (parentNodeIri.nonEmpty && !stringFormatter.isKnoraListIriStr(parentNodeIri.get)) { - throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR) - } - - if (projectIri.isEmpty) { - throw BadRequestException(PROJECT_IRI_MISSING_ERROR) - } - - if (!stringFormatter.isKnoraProjectIriStr(projectIri)) { - throw BadRequestException(PROJECT_IRI_INVALID_ERROR) - } - - if (labels.isEmpty) { - throw BadRequestException(LABEL_MISSING_ERROR) - } - - if (position.exists(_ < -1)) { - throw BadRequestException(INVALID_POSITION) - } +// private val stringFormatter = StringFormatter.getInstanceForConstantOntologies +// stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list IRI")) +// +// if (parentNodeIri.nonEmpty && !stringFormatter.isKnoraListIriStr(parentNodeIri.get)) { +// throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR) +// } +// +// if (projectIri.isEmpty) { +// throw BadRequestException(PROJECT_IRI_MISSING_ERROR) +// } +// +// if (!stringFormatter.isKnoraProjectIriStr(projectIri)) { +// throw BadRequestException(PROJECT_IRI_INVALID_ERROR) +// } +// +// if (labels.isEmpty) { +// throw BadRequestException(LABEL_MISSING_ERROR) +// } +// +// if (position.exists(_ < -1)) { +// throw BadRequestException(INVALID_POSITION) +// } def toJsValue: JsValue = createListNodeApiRequestADMFormat.write(this) /** * Escapes special characters within strings */ - def escape: CreateNodeApiRequestADM = { - val escapedLabels: Seq[StringLiteralV2] = labels.map { label => - val escapedLabel = - stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(s"Invalid label: ${label.value}")) - StringLiteralV2(value = escapedLabel, language = label.language) - } - val escapedComments = comments.map { comment => - val escapedComment = - stringFormatter.toSparqlEncodedString( - comment.value, - throw BadRequestException(s"Invalid comment: ${comment.value}") - ) - StringLiteralV2(value = escapedComment, language = comment.language) - } - val escapedName: Option[String] = name match { - case None => None - case Some(value: String) => - Some(stringFormatter.toSparqlEncodedString(value, throw BadRequestException(s"Invalid string: $value"))) - } - copy(labels = escapedLabels, comments = escapedComments, name = escapedName) - } +// def escape: CreateNodeApiRequestADM = { +// val escapedLabels: Seq[StringLiteralV2] = labels.map { label => +// val escapedLabel = +// stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(s"Invalid label: ${label.value}")) +// StringLiteralV2(value = escapedLabel, language = label.language) +// } +// val escapedComments = comments.map { comment => +// val escapedComment = +// stringFormatter.toSparqlEncodedString( +// comment.value, +// throw BadRequestException(s"Invalid comment: ${comment.value}") +// ) +// StringLiteralV2(value = escapedComment, language = comment.language) +// } +// val escapedName: Option[String] = name match { +// case None => None +// case Some(value: String) => +// Some(stringFormatter.toSparqlEncodedString(value, throw BadRequestException(s"Invalid string: $value"))) +// } +// copy(labels = escapedLabels, comments = escapedComments, name = escapedName) +// } } /** diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala index 6635625cfa..f3bbb7f38c 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala @@ -26,7 +26,9 @@ object ListsMessagesUtilADM { val LIST_NODE_IRI_INVALID_ERROR = "List node IRI is invalid." val PROJECT_IRI_MISSING_ERROR = "Project IRI cannot be empty." val PROJECT_IRI_INVALID_ERROR = "Project IRI is invalid." + val LIST_NAME_MISSING_ERROR = "List name cannot be empty." val LABEL_MISSING_ERROR = "At least one label needs to be supplied." + val COMMENT_MISSING_ERROR = "At least one comment needs to be supplied." val LIST_CREATE_PERMISSION_ERROR = "A list can only be created by the project or system administrator." val LIST_NODE_CREATE_PERMISSION_ERROR = "A list node can only be created by the project or system administrator." val LIST_CHANGE_PERMISSION_ERROR = "A list can only be changed by the project or system administrator." diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 1265035109..3c575f76c7 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -4,20 +4,22 @@ import org.knora.webapi.IRI import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ + COMMENT_MISSING_ERROR, INVALID_POSITION, LABEL_MISSING_ERROR, + LIST_NAME_MISSING_ERROR, LIST_NODE_IRI_INVALID_ERROR, LIST_NODE_IRI_MISSING_ERROR, PROJECT_IRI_INVALID_ERROR, PROJECT_IRI_MISSING_ERROR } import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 + +import scala.util.{Failure, Success, Try} //TODO: sprawdzic na koncu wszystkie czeki w messangerze czy poktrywaja sie tu i tak samo tresci bledow //TODO: possible to somehow merge all IRI related value objects? what about diff exception messages // either use below checks in route to throw custom exceptions for one IRI value object // or bring these matches here -//case Some(value) => Some(Comments.create(value).fold(e => throw e, v => v)) -//case None => None /** * List ListIRI value object. @@ -30,31 +32,15 @@ object ListIRI { if (value.isEmpty) { Left(BadRequestException(LIST_NODE_IRI_MISSING_ERROR)) } else { - val validatedValue = stringFormatter.validateAndEscapeIri( - value, - throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR) + val validatedValue = Try( + // move regex (string formatter functionality here) + stringFormatter.validateAndEscapeIri(value, throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) ) - Right(new ListIRI(validatedValue) {}) - } -} - -/** - * List CustomID value object. - */ -sealed abstract case class CustomID private (value: String) -object CustomID { - val stringFormatter = StringFormatter.getGeneralInstance - def create(value: String): Either[Throwable, CustomID] = - if (value.isEmpty) { -// TODO: if id is only optional empty condition shouldn't exist - Left(BadRequestException("Invalid custom node IRI")) - } else { - val validatedValue = stringFormatter.validateAndEscapeIri( - value, - throw BadRequestException(s"Invalid custom node IRI") - ) - Right(new CustomID(validatedValue) {}) + validatedValue match { + case Success(_) => Right(new ListIRI(value) {}) + case Failure(_) => Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) + } } } @@ -69,11 +55,14 @@ object ProjectIRI { if (value.isEmpty) { Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) } else { - val validatedValue = stringFormatter.validateAndEscapeProjectIri( - value, - throw BadRequestException(PROJECT_IRI_INVALID_ERROR) + val validatedValue = Try( + stringFormatter.validateAndEscapeProjectIri(value, throw BadRequestException(PROJECT_IRI_INVALID_ERROR)) ) - Right(new ProjectIRI(validatedValue) {}) + + validatedValue match { + case Success(_) => Right(new ProjectIRI(value) {}) + case Failure(_) => Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + } } } @@ -89,11 +78,17 @@ object RootNodeIRI { if (value.isEmpty) { Left(BadRequestException(s"Missing root node IRI")) } else { - val validatedValue = stringFormatter.validateAndEscapeIri( - value, - throw BadRequestException(s"Invalid root node IRI") + val validatedValue = Try( + stringFormatter.validateAndEscapeIri( + value, + throw BadRequestException(s"Invalid root node IRI") + ) ) - Right(new RootNodeIRI(validatedValue) {}) + + validatedValue match { + case Success(_) => Right(new RootNodeIRI(value) {}) + case Failure(_) => Left(BadRequestException(s"Invalid root node IRI")) + } } } @@ -104,7 +99,7 @@ sealed abstract case class ListName private (value: String) object ListName { def create(value: String): Either[Throwable, ListName] = if (value.isEmpty) { - Left(BadRequestException("Missing list name")) + Left(BadRequestException(LIST_NAME_MISSING_ERROR)) } else { Right(new ListName(value) {}) } @@ -143,7 +138,7 @@ sealed abstract case class Comments private (value: Seq[StringLiteralV2]) object Comments { def create(value: Seq[StringLiteralV2]): Either[Throwable, Comments] = if (value.isEmpty) { - Left(BadRequestException("Missing comments")) + Left(BadRequestException(COMMENT_MISSING_ERROR)) } else { Right(new Comments(value) {}) } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 3b8422e600..f5d2be2c06 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -36,7 +36,6 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.valueObjects.{ Comments, - CustomID, Labels, ListIRI, ListName, @@ -170,8 +169,8 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list item (root or child node) */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => - val maybeId: Option[CustomID] = apiRequest.id match { - case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) + val maybeId: Option[ListIRI] = apiRequest.id match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) case None => None } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 0225401039..0ef183be99 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -39,7 +39,6 @@ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayload import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.valueObjects.{ Comments, - CustomID, Labels, ListIRI, ListName, @@ -147,8 +146,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* create a list */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => - val maybeId: Option[CustomID] = apiRequest.id match { - case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) + val maybeId: Option[ListIRI] = apiRequest.id match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) case None => None } @@ -371,8 +370,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) post { /* add node to existing list node. the existing list node can be either the root or a child */ entity(as[CreateNodeApiRequestADM]) { apiRequest => requestContext => - val maybeId: Option[CustomID] = apiRequest.id match { - case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) + val maybeId: Option[ListIRI] = apiRequest.id match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) case None => None } diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index 71d1f08bd2..83ff4b61ce 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -20,221 +20,145 @@ package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.exceptions.BadRequestException -import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ - ChildNodeCreatePayloadADM, - ListCreatePayloadADM +import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ + COMMENT_MISSING_ERROR, + INVALID_POSITION, + LABEL_MISSING_ERROR, + LIST_NAME_MISSING_ERROR, + LIST_NODE_IRI_INVALID_ERROR, + LIST_NODE_IRI_MISSING_ERROR, + PROJECT_IRI_INVALID_ERROR, + PROJECT_IRI_MISSING_ERROR } -import org.knora.webapi.messages.admin.responder.listsmessages.{CreateNodeApiRequestADM, NodeCreatePayloadADM} import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.{IRI, UnitSpec} -import org.scalatest.enablers.Messaging.messagingNatureOfThrowable /** * This spec is used to test the creation of value objects of the [[ListsValueObjectsADM]]. */ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { -// TODO: these test should be simplified - UNIT TESTS about value objects only + "ListIRI value object" when { + val validListIri = "http://rdfh.ch/lists/0803/qBCJAdzZSCqC_2snW5Q7Nw" - private implicit val stringFormatter: StringFormatter = StringFormatter.getInstanceForConstantOntologies - - /** - * Convenience method returning the NodeCreatePayloadADM from the [[CreateNodeApiRequestADM]] object - * - * @param createNodeApiRequestADM the [[CreateNodeApiRequestADM]] object - * @return a [[NodeCreatePayloadADM]] - */ - private def createRootNodeCreatePayloadADM( - createNodeApiRequestADM: CreateNodeApiRequestADM - ): ListCreatePayloadADM = { - val maybeId: Option[CustomID] = createNodeApiRequestADM.id match { - case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) - case None => None + "created using empty value" should { + "throw BadRequestException" in { + ListIRI.create("") should equal(Left(BadRequestException(LIST_NODE_IRI_MISSING_ERROR))) + } } - - val maybeName: Option[ListName] = createNodeApiRequestADM.name match { - case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) - case None => None + "created using invalid value" should { + "throw BadRequestException" in { + ListIRI.create("123") should equal(Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR))) + } + } + "created using valid value" should { + "return value object that value equals to the value used to its creation" in { +// TODO: this probably doesn't make sense + ListIRI.create(validListIri).map(_.value should equal(validListIri)) + } } - - ListCreatePayloadADM( - id = maybeId, - projectIri = ProjectIRI.create(createNodeApiRequestADM.projectIri).fold(e => throw e, v => v), - name = maybeName, - labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), - comments = Comments.create(createNodeApiRequestADM.comments).fold(e => throw e, v => v) - ) } - /** - * Convenience method returning the [[ListCreatePayloadADM]] object - * - * @param id the optional custom IRI of the list node. - * @param parentNodeIri the optional IRI of the parent node. - * @param projectIri the IRI of the project. - * @param name the optional name of the list node. - * @param position the optional position of the node. - * @param labels labels of the list node. - * @param comments comments of the list node. - * @return a [[ListCreatePayloadADM]] - */ - private def createRootNodeApiRequestADM( - id: Option[IRI] = None, - parentNodeIri: Option[IRI] = None, - projectIri: IRI = "http://rdfh.ch/projects/0001", - name: Option[String] = None, - position: Option[Int] = None, - labels: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New label", language = Some("en"))), - comments: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New comment", language = Some("en"))) - ): CreateNodeApiRequestADM = CreateNodeApiRequestADM(id, parentNodeIri, projectIri, name, position, labels, comments) - - "When the ListCreatePayloadADM case class is created it" should { - "create a valid ListCreatePayloadADM" in { - - val request = createRootNodeApiRequestADM() - - val listCreatePayloadADM = createRootNodeCreatePayloadADM(request) - - listCreatePayloadADM.id should equal(request.id) - listCreatePayloadADM.projectIri.value should equal(request.projectIri) - listCreatePayloadADM.name.map(_.value) should equal(request.name) - listCreatePayloadADM.labels.value should equal(request.labels) - listCreatePayloadADM.comments.value should equal(request.comments) - - val otherRequest = createRootNodeApiRequestADM( - id = Some("http://rdfh.ch/lists/otherlistcustomid"), - parentNodeIri = None, - projectIri = "http://rdfh.ch/projects/0002", - name = Some("Uther Name"), - position = None, - labels = Seq(StringLiteralV2(value = "Other label", language = Some("en"))), - comments = Seq(StringLiteralV2(value = "Other comment", language = Some("en"))) - ) - - val otherRootNodeCreatePayloadADM = createRootNodeCreatePayloadADM(otherRequest) - - otherRootNodeCreatePayloadADM.id.map(_.value) should equal(otherRequest.id) - otherRootNodeCreatePayloadADM.projectIri.value should equal(otherRequest.projectIri) - otherRootNodeCreatePayloadADM.name.map(_.value) should equal(otherRequest.name) - otherRootNodeCreatePayloadADM.labels.value should equal(otherRequest.labels) - otherRootNodeCreatePayloadADM.comments.value should equal(otherRequest.comments) - - otherRootNodeCreatePayloadADM.id.map(_.value) should not equal request.id - otherRootNodeCreatePayloadADM.projectIri.value should not equal request.projectIri - otherRootNodeCreatePayloadADM.name.get.value should not equal request.name - otherRootNodeCreatePayloadADM.labels.value should not equal request.labels - otherRootNodeCreatePayloadADM.comments.value should not equal request.comments + "ProjectIRI value object" when { +// TODO: check string formatter project iri validation because passing just "http://rdfh.ch/projects/@@@@@@" works + val validProjectIri = "http://rdfh.ch/projects/0001" + + "created using empty value" should { + "throw BadRequestException" in { + ProjectIRI.create("") should equal(Left(BadRequestException(PROJECT_IRI_MISSING_ERROR))) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + ProjectIRI.create("123") should equal(Left(BadRequestException(PROJECT_IRI_INVALID_ERROR))) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { +// ProjectIRI.create(validProjectIri).map(_.value should equal(validProjectIri)) + ProjectIRI.create(validProjectIri) should not equal Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + } } } - /** - * Convenience method returning the NodeCreatePayloadADM from the [[CreateNodeApiRequestADM]] object - * - * @param createNodeApiRequestADM the [[CreateNodeApiRequestADM]] object - * @return a [[NodeCreatePayloadADM]] - */ - private def createChildNodeCreatePayloadADM( - createNodeApiRequestADM: CreateNodeApiRequestADM - ): ChildNodeCreatePayloadADM = { - val maybeId: Option[CustomID] = createNodeApiRequestADM.id match { - case Some(value) => Some(CustomID.create(value).fold(e => throw e, v => v)) - case None => None - } + "RootNodeIRI value object" when { +// TODO: check string formatter list iri validation because passing just "http://rdfh.ch" works + val validRootNodeIRI = "http://rdfh.ch/lists/0001/yWQEGXl53Z4C4DYJ-S2c5A" - val maybeParentNodeIri: Option[ListIRI] = createNodeApiRequestADM.parentNodeIri match { - case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) - case None => None + "created using empty value" should { + "throw BadRequestException" in { + RootNodeIRI.create("") should equal(Left(BadRequestException("Missing root node IRI"))) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + RootNodeIRI.create("123") should equal(Left(BadRequestException("Invalid root node IRI"))) + } } + "created using valid value" should { + "not throw BadRequestExceptions" in { + RootNodeIRI.create(validRootNodeIRI) should not equal Left(BadRequestException("Invalid root node IRI")) + } + } + } - val maybeName: Option[ListName] = createNodeApiRequestADM.name match { - case Some(value) => Some(ListName.create(value).fold(e => throw e, v => v)) - case None => None + "ListName value object" when { + val validListName = "It's valid list name example" + + "created using empty value" should { + "throw BadRequestException" in { + ListName.create("") should equal(Left(BadRequestException(LIST_NAME_MISSING_ERROR))) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + ListName.create(validListName) should not equal Left(BadRequestException(LIST_NAME_MISSING_ERROR)) + } } + } - val maybePosition: Option[Position] = createNodeApiRequestADM.position match { - case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) - case None => None + "Position value object" when { + val validPosition = 0 + + "created using invalid value" should { + "throw BadRequestException" in { + Position.create(-2) should equal(Left(BadRequestException(INVALID_POSITION))) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Position.create(validPosition) should not equal Left(BadRequestException(INVALID_POSITION)) + } } + } - ChildNodeCreatePayloadADM( - id = maybeId, - parentNodeIri = maybeParentNodeIri, - projectIri = ProjectIRI.create(createNodeApiRequestADM.projectIri).fold(e => throw e, v => v), - name = maybeName, - position = maybePosition, - labels = Labels.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v), - comments = Some(Comments.create(createNodeApiRequestADM.labels).fold(e => throw e, v => v)) - ) + "Labels value object" when { + val validLabels = Seq(StringLiteralV2(value = "New Label", language = Some("en"))) + + "created using empty value" should { + "throw BadRequestException" in { + Labels.create(Seq.empty) should equal(Left(BadRequestException(LABEL_MISSING_ERROR))) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Labels.create(validLabels) should not equal Left(BadRequestException(LABEL_MISSING_ERROR)) + } + } } - /** - * Convenience method returning the [[ChildNodeCreatePayloadADM]] object - * - * @param id the optional custom IRI of the list node. - * @param parentNodeIri the optional IRI of the parent node. - * @param projectIri the IRI of the project. - * @param name the optional name of the list node. - * @param position the optional position of the node. - * @param labels labels of the list node. - * @param comments comments of the list node. - * @return a [[ChildNodeCreatePayloadADM]] - */ - private def createChildNodeApiRequestADM( - id: Option[IRI] = None, - parentNodeIri: Option[IRI] = None, - projectIri: IRI = "http://rdfh.ch/projects/0001", - name: Option[String] = None, - position: Option[Int] = None, - labels: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "New label", language = Some("en"))), - comments: Seq[StringLiteralV2] = Seq(StringLiteralV2(value = "", language = None)) - ): CreateNodeApiRequestADM = - CreateNodeApiRequestADM(id, parentNodeIri, projectIri, name, position, labels, comments) - - "When the ChildNodeCreatePayloadADM case class is created it" should { - "create a valid ChildNodeCreatePayloadADM" in { - - val request = createChildNodeApiRequestADM() - - val childNodeCreatePayloadADM = createChildNodeCreatePayloadADM(request) - - childNodeCreatePayloadADM.id should equal(request.id) - childNodeCreatePayloadADM.parentNodeIri should equal(request.parentNodeIri) - childNodeCreatePayloadADM.projectIri.value should equal(request.projectIri) - childNodeCreatePayloadADM.name.map(_.value) should equal(request.name) - childNodeCreatePayloadADM.position.map(_.value) should equal(request.position) - childNodeCreatePayloadADM.labels.value should equal(request.labels) -// TODO: bring below back after separating ChildNodeCreateApiRequestADM from CreateNodeApiRequestADM -// childNodeCreatePayloadADM.comments.map(_.value) should equal(request.comments) - - val otherRequest = createChildNodeApiRequestADM( - id = Some("http://rdfh.ch/lists/otherlistcustomid"), - parentNodeIri = None, - projectIri = "http://rdfh.ch/projects/0002", - name = Some("Uther Name"), - position = None, - labels = Seq(StringLiteralV2(value = "Other label", language = Some("en"))), - comments = Seq(StringLiteralV2(value = "Other comment", language = Some("en"))) - ) - - val otherChildNodeCreatePayloadADM = createChildNodeCreatePayloadADM(otherRequest) - - otherChildNodeCreatePayloadADM.id.map(_.value) should equal(otherRequest.id) - otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) - otherChildNodeCreatePayloadADM.projectIri.value should equal(otherRequest.projectIri) - otherChildNodeCreatePayloadADM.name.map(_.value) should equal(otherRequest.name) - otherChildNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) - otherChildNodeCreatePayloadADM.labels.value should equal(otherRequest.labels) -// TODO: bring below back after separating ChildNodeCreateApiRequestADM from CreateNodeApiRequestADM -// otherChildNodeCreatePayloadADM.comments.map(_.value) should equal(otherRequest.comments) - - otherChildNodeCreatePayloadADM.id.map(_.value) should not equal request.id -// otherChildNodeCreatePayloadADM.parentNodeIri should equal(otherRequest.parentNodeIri) - otherChildNodeCreatePayloadADM.projectIri.value should not equal request.projectIri - otherChildNodeCreatePayloadADM.name.get.value should not equal request.name -// otherChildNodeCreatePayloadADM.position.map(_.value) should equal(otherRequest.position) - otherChildNodeCreatePayloadADM.labels.value should not equal request.labels - otherChildNodeCreatePayloadADM.comments.map(_.value) should not equal request.comments + "Comments value object" when { + val validComments = Seq(StringLiteralV2(value = "New Comment", language = Some("en"))) + + "created using empty value" should { + "throw BadRequestException" in { + Comments.create(Seq.empty) should equal(Left(BadRequestException(COMMENT_MISSING_ERROR))) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Comments.create(validComments) should not equal Left(BadRequestException(COMMENT_MISSING_ERROR)) + } } } } From f46eed2b7f0ea9b87d7d987a27454fc76e87604d Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Oct 2021 09:49:14 +0200 Subject: [PATCH 25/32] update value objects --- .../listsmessages/ListsMessagesADM.scala | 107 +++++++++--------- .../valueObjects/ListsValueObjectsADM.scala | 57 ++++++---- .../ListsValueObjectsADMSpec.scala | 6 +- 3 files changed, 91 insertions(+), 79 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 728c4cbdd7..351d27662e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -64,9 +64,10 @@ case class CreateNodeApiRequestADM( labels: Seq[StringLiteralV2], comments: Seq[StringLiteralV2] ) extends ListADMJsonProtocol { -// TODO: are below checks necessary anymore? CORRECT! but move all checks to value objects +// TODO: are below checks necessary anymore? NO! but move all checks to value objects +// then remove related Messages tests -// private val stringFormatter = StringFormatter.getInstanceForConstantOntologies + private val stringFormatter = StringFormatter.getInstanceForConstantOntologies // stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list IRI")) // // if (parentNodeIri.nonEmpty && !stringFormatter.isKnoraListIriStr(parentNodeIri.get)) { @@ -94,27 +95,28 @@ case class CreateNodeApiRequestADM( /** * Escapes special characters within strings */ -// def escape: CreateNodeApiRequestADM = { -// val escapedLabels: Seq[StringLiteralV2] = labels.map { label => -// val escapedLabel = -// stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(s"Invalid label: ${label.value}")) -// StringLiteralV2(value = escapedLabel, language = label.language) -// } -// val escapedComments = comments.map { comment => -// val escapedComment = -// stringFormatter.toSparqlEncodedString( -// comment.value, -// throw BadRequestException(s"Invalid comment: ${comment.value}") -// ) -// StringLiteralV2(value = escapedComment, language = comment.language) -// } -// val escapedName: Option[String] = name match { -// case None => None -// case Some(value: String) => -// Some(stringFormatter.toSparqlEncodedString(value, throw BadRequestException(s"Invalid string: $value"))) -// } -// copy(labels = escapedLabels, comments = escapedComments, name = escapedName) -// } +// TODO: what about this code? Is it used at all? + def escape: CreateNodeApiRequestADM = { + val escapedLabels: Seq[StringLiteralV2] = labels.map { label => + val escapedLabel = + stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(s"Invalid label: ${label.value}")) + StringLiteralV2(value = escapedLabel, language = label.language) + } + val escapedComments = comments.map { comment => + val escapedComment = + stringFormatter.toSparqlEncodedString( + comment.value, + throw BadRequestException(s"Invalid comment: ${comment.value}") + ) + StringLiteralV2(value = escapedComment, language = comment.language) + } + val escapedName: Option[String] = name match { + case None => None + case Some(value: String) => + Some(stringFormatter.toSparqlEncodedString(value, throw BadRequestException(s"Invalid string: $value"))) + } + copy(labels = escapedLabels, comments = escapedComments, name = escapedName) + } } /** @@ -140,35 +142,36 @@ case class ChangeNodeInfoApiRequestADM( private val stringFormatter = StringFormatter.getInstanceForConstantOntologies - if (listIri.isEmpty) { - throw BadRequestException(s"IRI of list item is missing.") - } - - if (!stringFormatter.isKnoraListIriStr(listIri)) { - throw BadRequestException(s"Invalid IRI is given: $listIri.") - } - - // Check that project Iri is given - if (projectIri.isEmpty) { - throw BadRequestException(PROJECT_IRI_MISSING_ERROR) - } - - // Verify the project IRI - if (!stringFormatter.isKnoraProjectIriStr(projectIri)) { - throw BadRequestException(PROJECT_IRI_INVALID_ERROR) - } - - if (hasRootNode.isDefined && !stringFormatter.isKnoraListIriStr(hasRootNode.get)) { - throw BadRequestException(s"Invalid root node IRI is given.") - } - // If payload contains labels, they should not be empty - if (labels.exists(_.isEmpty)) { - throw BadRequestException(UPDATE_REQUEST_EMPTY_LABEL_ERROR) - } - - if (position.exists(_ < -1)) { - throw BadRequestException(INVALID_POSITION) - } +// if (listIri.isEmpty) { +// throw BadRequestException(s"IRI of list item is missing.") +// } +// +// if (!stringFormatter.isKnoraListIriStr(listIri)) { +// throw BadRequestException(s"Invalid IRI is given: $listIri.") +// } +// +// // Check that project Iri is given +// if (projectIri.isEmpty) { +// throw BadRequestException(PROJECT_IRI_MISSING_ERROR) +// } +// +// // Verify the project IRI +// if (!stringFormatter.isKnoraProjectIriStr(projectIri)) { +// throw BadRequestException(PROJECT_IRI_INVALID_ERROR) +// } +////TODO: how to perform this kind of check in valu objects if isn't possible to know there if it is hasRootNode +//// or something else (one list value object shared for all lists related properties)? +// if (hasRootNode.isDefined && !stringFormatter.isKnoraListIriStr(hasRootNode.get)) { +// throw BadRequestException(s"Invalid root node IRI is given.") +// } +// // If payload contains labels, they should not be empty +// if (labels.exists(_.isEmpty)) { +// throw BadRequestException(UPDATE_REQUEST_EMPTY_LABEL_ERROR) +// } +// +// if (position.exists(_ < -1)) { +// throw BadRequestException(INVALID_POSITION) +// } def toJsValue: JsValue = changeListInfoApiRequestADMFormat.write(this) } diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 3c575f76c7..1ea313b9f6 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -1,6 +1,5 @@ package org.knora.webapi.messages.admin.responder.valueObjects -import org.knora.webapi.IRI import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ @@ -32,14 +31,17 @@ object ListIRI { if (value.isEmpty) { Left(BadRequestException(LIST_NODE_IRI_MISSING_ERROR)) } else { - val validatedValue = Try( - // move regex (string formatter functionality here) - stringFormatter.validateAndEscapeIri(value, throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) - ) + if (value.nonEmpty && !stringFormatter.isKnoraListIriStr(value)) { + Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) + } else { + val validatedValue = Try( + stringFormatter.validateAndEscapeIri(value, throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) + ) - validatedValue match { - case Success(_) => Right(new ListIRI(value) {}) - case Failure(_) => Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) + validatedValue match { + case Success(_) => Right(new ListIRI(value) {}) + case Failure(_) => Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) + } } } } @@ -55,13 +57,17 @@ object ProjectIRI { if (value.isEmpty) { Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) } else { - val validatedValue = Try( - stringFormatter.validateAndEscapeProjectIri(value, throw BadRequestException(PROJECT_IRI_INVALID_ERROR)) - ) + if (value.nonEmpty && !stringFormatter.isKnoraProjectIriStr((value))) { + Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + } else { + val validatedValue = Try( + stringFormatter.validateAndEscapeProjectIri(value, throw BadRequestException(PROJECT_IRI_INVALID_ERROR)) + ) - validatedValue match { - case Success(_) => Right(new ProjectIRI(value) {}) - case Failure(_) => Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + validatedValue match { + case Success(_) => Right(new ProjectIRI(value) {}) + case Failure(_) => Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + } } } } @@ -74,20 +80,23 @@ object RootNodeIRI { val stringFormatter = StringFormatter.getGeneralInstance def create(value: String): Either[Throwable, RootNodeIRI] = - // TODO: if id is only optional empty condition shouldn't exist if (value.isEmpty) { Left(BadRequestException(s"Missing root node IRI")) } else { - val validatedValue = Try( - stringFormatter.validateAndEscapeIri( - value, - throw BadRequestException(s"Invalid root node IRI") + if (value.nonEmpty && !stringFormatter.isKnoraListIriStr(value)) { + Left(BadRequestException(s"Invalid root node IRI")) + } else { + val validatedValue = Try( + stringFormatter.validateAndEscapeIri( + value, + throw BadRequestException(s"Invalid root node IRI") + ) ) - ) - validatedValue match { - case Success(_) => Right(new RootNodeIRI(value) {}) - case Failure(_) => Left(BadRequestException(s"Invalid root node IRI")) + validatedValue match { + case Success(_) => Right(new RootNodeIRI(value) {}) + case Failure(_) => Left(BadRequestException(s"Invalid root node IRI")) + } } } } @@ -111,7 +120,7 @@ object ListName { sealed abstract case class Position private (value: Int) object Position { def create(value: Int): Either[Throwable, Position] = - if (value < -1) { // TODO: what should be the criteria? + if (value < -1) { Left(BadRequestException(INVALID_POSITION)) } else { Right(new Position(value) {}) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index 83ff4b61ce..ddd8787b14 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -53,8 +53,9 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using valid value" should { "return value object that value equals to the value used to its creation" in { -// TODO: this probably doesn't make sense - ListIRI.create(validListIri).map(_.value should equal(validListIri)) +//// TODO: this probably doesn't make sense +// ListIRI.create(validListIri).map(_.value should equal(validListIri)) + ListIRI.create(validListIri) should not equal Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) } } } @@ -82,7 +83,6 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "RootNodeIRI value object" when { -// TODO: check string formatter list iri validation because passing just "http://rdfh.ch" works val validRootNodeIRI = "http://rdfh.ch/lists/0001/yWQEGXl53Z4C4DYJ-S2c5A" "created using empty value" should { From a1a66de0eece0012c2d592fe03cf37dde8263600 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Oct 2021 09:53:33 +0200 Subject: [PATCH 26/32] remove RootNodeIRI value object --- .../listsmessages/ListPayloadsADM.scala | 5 ++-- .../valueObjects/ListsValueObjectsADM.scala | 29 ------------------- .../admin/lists/NewListsRouteADMFeature.scala | 7 ++--- .../admin/lists/OldListsRouteADMFeature.scala | 7 ++--- .../ListsValueObjectsADMSpec.scala | 20 ------------- 5 files changed, 8 insertions(+), 60 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index b310a6f08e..faa2ecb0cb 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -7,8 +7,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ ListIRI, ListName, Position, - ProjectIRI, - RootNodeIRI + ProjectIRI } /** @@ -40,7 +39,7 @@ object NodeCreatePayloadADM { final case class NodeInfoChangePayloadADM( listIri: ListIRI, projectIri: ProjectIRI, - hasRootNode: Option[RootNodeIRI] = None, + hasRootNode: Option[ListIRI] = None, position: Option[Position] = None, name: Option[ListName] = None, labels: Option[Labels] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 1ea313b9f6..36077c112d 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -72,35 +72,6 @@ object ProjectIRI { } } -/** - * List RootNodeIRI value object. - */ -sealed abstract case class RootNodeIRI private (value: String) -object RootNodeIRI { - val stringFormatter = StringFormatter.getGeneralInstance - - def create(value: String): Either[Throwable, RootNodeIRI] = - if (value.isEmpty) { - Left(BadRequestException(s"Missing root node IRI")) - } else { - if (value.nonEmpty && !stringFormatter.isKnoraListIriStr(value)) { - Left(BadRequestException(s"Invalid root node IRI")) - } else { - val validatedValue = Try( - stringFormatter.validateAndEscapeIri( - value, - throw BadRequestException(s"Invalid root node IRI") - ) - ) - - validatedValue match { - case Success(_) => Right(new RootNodeIRI(value) {}) - case Failure(_) => Left(BadRequestException(s"Invalid root node IRI")) - } - } - } -} - /** * List ListName value object. */ diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index f5d2be2c06..17f54e39da 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -40,8 +40,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ ListIRI, ListName, Position, - ProjectIRI, - RootNodeIRI + ProjectIRI } import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} @@ -344,8 +343,8 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) val listIri = ListIRI.create(apiRequest.listIri).fold(e => throw e, v => v) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) - val maybeHasRootNode: Option[RootNodeIRI] = apiRequest.hasRootNode match { - case Some(value) => Some(RootNodeIRI.create(value).fold(e => throw e, v => v)) + val maybeHasRootNode: Option[ListIRI] = apiRequest.hasRootNode match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) case None => None } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 0ef183be99..1905dd528b 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -43,8 +43,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ ListIRI, ListName, Position, - ProjectIRI, - RootNodeIRI + ProjectIRI } import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} @@ -275,8 +274,8 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) val listIri = ListIRI.create(apiRequest.listIri).fold(e => throw e, v => v) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) - val maybeHasRootNode: Option[RootNodeIRI] = apiRequest.hasRootNode match { - case Some(value) => Some(RootNodeIRI.create(value).fold(e => throw e, v => v)) + val maybeHasRootNode: Option[ListIRI] = apiRequest.hasRootNode match { + case Some(value) => Some(ListIRI.create(value).fold(e => throw e, v => v)) case None => None } diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index ddd8787b14..45b7eabc28 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -82,26 +82,6 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } } - "RootNodeIRI value object" when { - val validRootNodeIRI = "http://rdfh.ch/lists/0001/yWQEGXl53Z4C4DYJ-S2c5A" - - "created using empty value" should { - "throw BadRequestException" in { - RootNodeIRI.create("") should equal(Left(BadRequestException("Missing root node IRI"))) - } - } - "created using invalid value" should { - "throw BadRequestException" in { - RootNodeIRI.create("123") should equal(Left(BadRequestException("Invalid root node IRI"))) - } - } - "created using valid value" should { - "not throw BadRequestExceptions" in { - RootNodeIRI.create(validRootNodeIRI) should not equal Left(BadRequestException("Invalid root node IRI")) - } - } - } - "ListName value object" when { val validListName = "It's valid list name example" From 2f12998ca21435b23fc8471842ac7cb4aebaf149 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Oct 2021 12:07:47 +0200 Subject: [PATCH 27/32] add more checks to value objects + update tests --- .../listsmessages/ListPayloadsADM.scala | 1 - .../listsmessages/ListsMessagesADM.scala | 42 +++++++-------- .../listsmessages/ListsMessagesUtilADM.scala | 3 ++ .../valueObjects/ListsValueObjectsADM.scala | 51 ++++++++++++++++--- .../ListsValueObjectsADMSpec.scala | 29 +++++++++-- 5 files changed, 93 insertions(+), 33 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala index faa2ecb0cb..e917c7ccce 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala @@ -1,6 +1,5 @@ package org.knora.webapi.messages.admin.responder.listsmessages -import org.knora.webapi.IRI import org.knora.webapi.messages.admin.responder.valueObjects.{ Comments, Labels, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 351d27662e..a56a32bcb9 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -96,27 +96,27 @@ case class CreateNodeApiRequestADM( * Escapes special characters within strings */ // TODO: what about this code? Is it used at all? - def escape: CreateNodeApiRequestADM = { - val escapedLabels: Seq[StringLiteralV2] = labels.map { label => - val escapedLabel = - stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(s"Invalid label: ${label.value}")) - StringLiteralV2(value = escapedLabel, language = label.language) - } - val escapedComments = comments.map { comment => - val escapedComment = - stringFormatter.toSparqlEncodedString( - comment.value, - throw BadRequestException(s"Invalid comment: ${comment.value}") - ) - StringLiteralV2(value = escapedComment, language = comment.language) - } - val escapedName: Option[String] = name match { - case None => None - case Some(value: String) => - Some(stringFormatter.toSparqlEncodedString(value, throw BadRequestException(s"Invalid string: $value"))) - } - copy(labels = escapedLabels, comments = escapedComments, name = escapedName) - } +// def escape: CreateNodeApiRequestADM = { +// val escapedLabels: Seq[StringLiteralV2] = labels.map { label => +// val escapedLabel = +// stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(s"Invalid label: ${label.value}")) +// StringLiteralV2(value = escapedLabel, language = label.language) +// } +// val escapedComments = comments.map { comment => +// val escapedComment = +// stringFormatter.toSparqlEncodedString( +// comment.value, +// throw BadRequestException(s"Invalid comment: ${comment.value}") +// ) +// StringLiteralV2(value = escapedComment, language = comment.language) +// } +// val escapedName: Option[String] = name match { +// case None => None +// case Some(value: String) => +// Some(stringFormatter.toSparqlEncodedString(value, throw BadRequestException(s"Invalid string: $value"))) +// } +// copy(labels = escapedLabels, comments = escapedComments, name = escapedName) +// } } /** diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala index f3bbb7f38c..7571e0b9ec 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala @@ -27,8 +27,11 @@ object ListsMessagesUtilADM { val PROJECT_IRI_MISSING_ERROR = "Project IRI cannot be empty." val PROJECT_IRI_INVALID_ERROR = "Project IRI is invalid." val LIST_NAME_MISSING_ERROR = "List name cannot be empty." + val LIST_NAME_INVALID_ERROR = "List name is invalid." val LABEL_MISSING_ERROR = "At least one label needs to be supplied." + val LABEL_INVALID_ERROR = "Invalid label." val COMMENT_MISSING_ERROR = "At least one comment needs to be supplied." + val COMMENT_INVALID_ERROR = "Invalid comment." val LIST_CREATE_PERMISSION_ERROR = "A list can only be created by the project or system administrator." val LIST_NODE_CREATE_PERMISSION_ERROR = "A list node can only be created by the project or system administrator." val LIST_CHANGE_PERMISSION_ERROR = "A list can only be changed by the project or system administrator." diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 36077c112d..5326d521aa 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -3,9 +3,12 @@ package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ + COMMENT_INVALID_ERROR, COMMENT_MISSING_ERROR, INVALID_POSITION, + LABEL_INVALID_ERROR, LABEL_MISSING_ERROR, + LIST_NAME_INVALID_ERROR, LIST_NAME_MISSING_ERROR, LIST_NODE_IRI_INVALID_ERROR, LIST_NODE_IRI_MISSING_ERROR, @@ -39,8 +42,8 @@ object ListIRI { ) validatedValue match { - case Success(_) => Right(new ListIRI(value) {}) - case Failure(_) => Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) + case Success(iri) => Right(new ListIRI(iri) {}) + case Failure(_) => Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) } } } @@ -57,7 +60,8 @@ object ProjectIRI { if (value.isEmpty) { Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) } else { - if (value.nonEmpty && !stringFormatter.isKnoraProjectIriStr((value))) { + // TODO: nonEmpty vs isDefined ?? + if (value.nonEmpty && !stringFormatter.isKnoraProjectIriStr(value)) { Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) } else { val validatedValue = Try( @@ -65,8 +69,8 @@ object ProjectIRI { ) validatedValue match { - case Success(_) => Right(new ProjectIRI(value) {}) - case Failure(_) => Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + case Success(iri) => Right(new ProjectIRI(iri) {}) + case Failure(_) => Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) } } } @@ -77,11 +81,20 @@ object ProjectIRI { */ sealed abstract case class ListName private (value: String) object ListName { + val stringFormatter = StringFormatter.getGeneralInstance + def create(value: String): Either[Throwable, ListName] = if (value.isEmpty) { Left(BadRequestException(LIST_NAME_MISSING_ERROR)) } else { - Right(new ListName(value) {}) + val validatedValue = Try( + stringFormatter.toSparqlEncodedString(value, throw BadRequestException(LIST_NAME_INVALID_ERROR)) + ) + + validatedValue match { + case Success(name) => Right(new ListName(name) {}) + case Failure(_) => Left(BadRequestException(LIST_NAME_INVALID_ERROR)) + } } } @@ -103,11 +116,22 @@ object Position { */ sealed abstract case class Labels private (value: Seq[StringLiteralV2]) object Labels { + val stringFormatter = StringFormatter.getGeneralInstance + def create(value: Seq[StringLiteralV2]): Either[Throwable, Labels] = if (value.isEmpty) { Left(BadRequestException(LABEL_MISSING_ERROR)) } else { - Right(new Labels(value) {}) + val validatedLabels = Try(value.map { label => + val validatedLabel = + stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(LABEL_INVALID_ERROR)) + StringLiteralV2(value = validatedLabel, language = label.language) + }) + + validatedLabels match { + case Success(valid) => Right(new Labels(valid) {}) + case Failure(_) => Left(BadRequestException(LABEL_INVALID_ERROR)) + } } } @@ -116,10 +140,21 @@ object Labels { */ sealed abstract case class Comments private (value: Seq[StringLiteralV2]) object Comments { + val stringFormatter = StringFormatter.getGeneralInstance + def create(value: Seq[StringLiteralV2]): Either[Throwable, Comments] = if (value.isEmpty) { Left(BadRequestException(COMMENT_MISSING_ERROR)) } else { - Right(new Comments(value) {}) + val validatedComments = Try(value.map { comment => + val validatedComment = + stringFormatter.toSparqlEncodedString(comment.value, throw BadRequestException(COMMENT_INVALID_ERROR)) + StringLiteralV2(value = validatedComment, language = comment.language) + }) + + validatedComments match { + case Success(valid) => Right(new Comments(valid) {}) + case Failure(_) => Left(BadRequestException(COMMENT_INVALID_ERROR)) + } } } diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index 45b7eabc28..41e1e627b8 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -21,9 +21,12 @@ package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ + COMMENT_INVALID_ERROR, COMMENT_MISSING_ERROR, INVALID_POSITION, + LABEL_INVALID_ERROR, LABEL_MISSING_ERROR, + LIST_NAME_INVALID_ERROR, LIST_NAME_MISSING_ERROR, LIST_NODE_IRI_INVALID_ERROR, LIST_NODE_IRI_MISSING_ERROR, @@ -90,9 +93,15 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { ListName.create("") should equal(Left(BadRequestException(LIST_NAME_MISSING_ERROR))) } } + "created using invalid value" should { + "throw BadRequestException" in { +// TODO: should this: "\"It's invalid list name example\"" pass? + ListName.create("\r") should equal(Left(BadRequestException(LIST_NAME_INVALID_ERROR))) + } + } "created using valid value" should { "not throw BadRequestExceptions" in { - ListName.create(validListName) should not equal Left(BadRequestException(LIST_NAME_MISSING_ERROR)) + ListName.create(validListName) should not equal Left(BadRequestException(LIST_NAME_INVALID_ERROR)) } } } @@ -114,30 +123,44 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { "Labels value object" when { val validLabels = Seq(StringLiteralV2(value = "New Label", language = Some("en"))) + val invalidLabels = Seq(StringLiteralV2(value = "\r", language = Some("en"))) "created using empty value" should { "throw BadRequestException" in { Labels.create(Seq.empty) should equal(Left(BadRequestException(LABEL_MISSING_ERROR))) } } + "created using invalid value" should { + "throw BadRequestException" in { + // TODO: should this: "\"It's invalid list name example\"" pass? + Labels.create(invalidLabels) should equal(Left(BadRequestException(LABEL_INVALID_ERROR))) + } + } "created using valid value" should { "not throw BadRequestExceptions" in { - Labels.create(validLabels) should not equal Left(BadRequestException(LABEL_MISSING_ERROR)) + Labels.create(validLabels) should not equal Left(BadRequestException(LABEL_INVALID_ERROR)) } } } "Comments value object" when { val validComments = Seq(StringLiteralV2(value = "New Comment", language = Some("en"))) + val invalidComments = Seq(StringLiteralV2(value = "\r", language = Some("en"))) "created using empty value" should { "throw BadRequestException" in { Comments.create(Seq.empty) should equal(Left(BadRequestException(COMMENT_MISSING_ERROR))) } } + "created using invalid value" should { + "throw BadRequestException" in { + // TODO: should this: "\"It's invalid list name example\"" pass? + Comments.create(invalidComments) should equal(Left(BadRequestException(COMMENT_INVALID_ERROR))) + } + } "created using valid value" should { "not throw BadRequestExceptions" in { - Comments.create(validComments) should not equal Left(BadRequestException(COMMENT_MISSING_ERROR)) + Comments.create(validComments) should not equal Left(BadRequestException(COMMENT_INVALID_ERROR)) } } } From 833a6d9ed3fc999077de7a124ed9d9c27061bcae Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Oct 2021 15:26:26 +0200 Subject: [PATCH 28/32] remove redundand tests --- .../listsmessages/ListsMessagesADMSpec.scala | 280 +----------------- .../ListsValueObjectsADMSpec.scala | 6 +- 2 files changed, 5 insertions(+), 281 deletions(-) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index d2d42511aa..64e8851d1a 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -22,12 +22,9 @@ package org.knora.webapi.messages.admin.responder.listsmessages import java.util.UUID import com.typesafe.config.ConfigFactory import org.knora.webapi.CoreSpec -import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} +import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ -import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ - ChildNodeCreatePayloadADM, - ListCreatePayloadADM -} +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.ChildNodeCreatePayloadADM import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListIRI, ProjectIRI, Position} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} import org.knora.webapi.sharedtestdata.{SharedListsTestDataADM, SharedTestDataADM} @@ -146,72 +143,6 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li converted.children should be(children) } - "throw 'BadRequestException' for `CreateNodeApiRequestADM` when project IRI is empty" in { - - val payload = - s""" - |{ - | "projectIri": "", - | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(PROJECT_IRI_MISSING_ERROR) - - } - - "throw 'BadRequestException' for `CreateNodeApiRequestADM` when project IRI is invalid" in { - - val payload = - s""" - |{ - | "projectIri": "not an IRI", - | "labels": [{ "value": "Neue Liste", "language": "de"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(PROJECT_IRI_INVALID_ERROR) - } - - "throw 'BadRequestException' for `CreateNodeApiRequestADM` when labels is empty" in { - - val payload = - s""" - |{ - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(LABEL_MISSING_ERROR) - } - - "throw a 'BadRequestException' for `CreateNodeApiRequestADM` when an invalid list IRI is given" in { - - val payload = - s""" - |{ - | "id": "invalid-list-IRI", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [{ "value": "New List", "language": "en"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal("Invalid list IRI") - } - "throw 'BadRequestException' for `CreateNodeApiRequestADM` when value of a label is missing" in { val payload = @@ -245,105 +176,6 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li thrown.getMessage should equal("String value is missing.") } - "throw 'BadRequestException' for `ChangeNodeInfoApiRequestADM` when list IRI is empty" in { - - val payload = - s""" - |{ - | "listIri": "", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [{ "value": "Neue geönderte Liste", "language": "de"}, { "value": "Changed list", "language": "en"}], - | "comments": [{ "value": "Neuer Kommentar", "language": "de"}, { "value": "New comment", "language": "en"}] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[ChangeNodeInfoApiRequestADM] - - thrown.getMessage should equal("IRI of list item is missing.") - } - - "throw 'BadRequestException' for `ChangeNodeInfoApiRequestADM` when list IRI is invalid" in { - val invalidIri = "notvalidIRI" - val payload = - s""" - |{ - | "listIri": "$invalidIri", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [{ "value": "Neue geönderte Liste", "language": "de"}, { "value": "Changed list", "language": "en"}], - | "comments": [{ "value": "Neuer Kommentar", "language": "de"}, { "value": "New comment", "language": "en"}] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[ChangeNodeInfoApiRequestADM] - - thrown.getMessage should equal(s"Invalid IRI is given: $invalidIri.") - } - - "throw 'BadRequestException' for `ChangeNodeInfoApiRequestADM` when project IRI is empty" in { - - val payload = - s""" - |{ - | "listIri": "$exampleListIri", - | "projectIri": "", - | "labels": [{ "value": "Neue geönderte Liste", "language": "de"}, { "value": "Changed list", "language": "en"}] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[ChangeNodeInfoApiRequestADM] - - thrown.getMessage should equal(PROJECT_IRI_MISSING_ERROR) - } - - "throw 'BadRequestException' for `ChangeNodeInfoApiRequestADM` when project IRI is invalid" in { - - val payload = - s""" - |{ - | "listIri": "$exampleListIri", - | "projectIri": "notvalidIRI", - | "name": "a new name" - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[ChangeNodeInfoApiRequestADM] - - thrown.getMessage should equal(PROJECT_IRI_INVALID_ERROR) - } - - "throw 'BadRequestException' for `ChangeNodeInfoApiRequestADM` when labels are empty" in { - - val payload = - s""" - |{ - | "listIri": "$exampleListIri", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[ChangeNodeInfoApiRequestADM] - - thrown.getMessage should equal(UPDATE_REQUEST_EMPTY_LABEL_ERROR) - } - - "throw 'BadRequestException' for `ChangeNodeInfoApiRequestADM` when position is invalid" in { - - val payload = - s""" - |{ - | "listIri": "$exampleListIri", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "position": -2 - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[ChangeNodeInfoApiRequestADM] - - thrown.getMessage should equal(INVALID_POSITION) - } - "throw 'BadRequestException' if invalid position given in payload of `createChildNodeRequest`" in { val caught = intercept[BadRequestException]( ListChildNodeCreateRequestADM( @@ -368,114 +200,6 @@ class ListsMessagesADMSpec extends CoreSpec(ListsMessagesADMSpec.config) with Li assert(caught.getMessage === INVALID_POSITION) } - "throw 'BadRequestException' for `createChildNodeRequest` when no parent node iri is given" in { - - val payload = - s""" - |{ - | "parentNodeIri": "", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [{ "value": "Neuer List Node", "language": "de"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(LIST_NODE_IRI_INVALID_ERROR) - - } - - "throw 'BadRequestException' for `createChildNodeRequest` when parent node iri is invalid" in { - - val payload = - s""" - |{ - | "parentNodeIri": "notvalidIRI", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [{ "value": "Neuer List Node", "language": "de"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(LIST_NODE_IRI_INVALID_ERROR) - - } - - "throw 'BadRequestException' for `createChildNodeRequest` when project iri is empty" in { - - val payload = - s""" - |{ - | "parentNodeIri": "$exampleListIri", - | "projectIri": "", - | "labels": [{ "value": "Neuer List Node", "language": "de"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(PROJECT_IRI_MISSING_ERROR) - - } - - "throw 'BadRequestException' for `createChildNodeRequest` when project iri is invalid" in { - - val payload = - s""" - |{ - | "parentNodeIri": "$exampleListIri", - | "projectIri": "notvalidIRI", - | "labels": [{ "value": "Neuer List Node", "language": "de"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(PROJECT_IRI_INVALID_ERROR) - - } - - "throw 'BadRequestException' for `createChildNodeRequest` when labels are empty" in { - - val payload = - s""" - |{ - | "parentNodeIri": "$exampleListIri", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal(LABEL_MISSING_ERROR) - - } - - "throw 'BadRequestException' for `createChildNodeRequest` when custom iri of the child node is invalid" in { - - val payload = - s""" - |{ "id": "invalid-list-node-IRI", - | "parentNodeIri": "$exampleListIri", - | "projectIri": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", - | "labels": [{ "value": "Neuer List Node", "language": "de"}], - | "comments": [] - |} - """.stripMargin - - val thrown = the[BadRequestException] thrownBy payload.parseJson.convertTo[CreateNodeApiRequestADM] - - thrown.getMessage should equal("Invalid list IRI") - - } - "throw 'BadRequestException' for `ChangeNodePositionApiRequestADM` when no parent node iri is given" in { val payload = diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index 41e1e627b8..96882de2ae 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -34,7 +34,7 @@ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtil PROJECT_IRI_MISSING_ERROR } import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import org.knora.webapi.{IRI, UnitSpec} +import org.knora.webapi.UnitSpec /** * This spec is used to test the creation of value objects of the [[ListsValueObjectsADM]]. @@ -51,7 +51,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using invalid value" should { "throw BadRequestException" in { - ListIRI.create("123") should equal(Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR))) + ListIRI.create("not a list IRI") should equal(Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR))) } } "created using valid value" should { @@ -74,7 +74,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using invalid value" should { "throw BadRequestException" in { - ProjectIRI.create("123") should equal(Left(BadRequestException(PROJECT_IRI_INVALID_ERROR))) + ProjectIRI.create("not a project IRI") should equal(Left(BadRequestException(PROJECT_IRI_INVALID_ERROR))) } } "created using valid value" should { From 9f9bc9cac7fc545247e76d622a4f92cfbf7bbd09 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 27 Oct 2021 17:36:39 +0200 Subject: [PATCH 29/32] fix optional comments creating child node --- .../listsmessages/ListsMessagesADM.scala | 86 ------------------- .../admin/lists/NewListsRouteADMFeature.scala | 48 +++++++---- .../admin/lists/OldListsRouteADMFeature.scala | 14 +-- 3 files changed, 37 insertions(+), 111 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index a56a32bcb9..59e47363bb 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -64,59 +64,7 @@ case class CreateNodeApiRequestADM( labels: Seq[StringLiteralV2], comments: Seq[StringLiteralV2] ) extends ListADMJsonProtocol { -// TODO: are below checks necessary anymore? NO! but move all checks to value objects -// then remove related Messages tests - - private val stringFormatter = StringFormatter.getInstanceForConstantOntologies -// stringFormatter.validateOptionalListIri(id, throw BadRequestException(s"Invalid list IRI")) -// -// if (parentNodeIri.nonEmpty && !stringFormatter.isKnoraListIriStr(parentNodeIri.get)) { -// throw BadRequestException(LIST_NODE_IRI_INVALID_ERROR) -// } -// -// if (projectIri.isEmpty) { -// throw BadRequestException(PROJECT_IRI_MISSING_ERROR) -// } -// -// if (!stringFormatter.isKnoraProjectIriStr(projectIri)) { -// throw BadRequestException(PROJECT_IRI_INVALID_ERROR) -// } -// -// if (labels.isEmpty) { -// throw BadRequestException(LABEL_MISSING_ERROR) -// } -// -// if (position.exists(_ < -1)) { -// throw BadRequestException(INVALID_POSITION) -// } - def toJsValue: JsValue = createListNodeApiRequestADMFormat.write(this) - - /** - * Escapes special characters within strings - */ -// TODO: what about this code? Is it used at all? -// def escape: CreateNodeApiRequestADM = { -// val escapedLabels: Seq[StringLiteralV2] = labels.map { label => -// val escapedLabel = -// stringFormatter.toSparqlEncodedString(label.value, throw BadRequestException(s"Invalid label: ${label.value}")) -// StringLiteralV2(value = escapedLabel, language = label.language) -// } -// val escapedComments = comments.map { comment => -// val escapedComment = -// stringFormatter.toSparqlEncodedString( -// comment.value, -// throw BadRequestException(s"Invalid comment: ${comment.value}") -// ) -// StringLiteralV2(value = escapedComment, language = comment.language) -// } -// val escapedName: Option[String] = name match { -// case None => None -// case Some(value: String) => -// Some(stringFormatter.toSparqlEncodedString(value, throw BadRequestException(s"Invalid string: $value"))) -// } -// copy(labels = escapedLabels, comments = escapedComments, name = escapedName) -// } } /** @@ -139,40 +87,6 @@ case class ChangeNodeInfoApiRequestADM( labels: Option[Seq[StringLiteralV2]] = None, comments: Option[Seq[StringLiteralV2]] = None ) extends ListADMJsonProtocol { - - private val stringFormatter = StringFormatter.getInstanceForConstantOntologies - -// if (listIri.isEmpty) { -// throw BadRequestException(s"IRI of list item is missing.") -// } -// -// if (!stringFormatter.isKnoraListIriStr(listIri)) { -// throw BadRequestException(s"Invalid IRI is given: $listIri.") -// } -// -// // Check that project Iri is given -// if (projectIri.isEmpty) { -// throw BadRequestException(PROJECT_IRI_MISSING_ERROR) -// } -// -// // Verify the project IRI -// if (!stringFormatter.isKnoraProjectIriStr(projectIri)) { -// throw BadRequestException(PROJECT_IRI_INVALID_ERROR) -// } -////TODO: how to perform this kind of check in valu objects if isn't possible to know there if it is hasRootNode -//// or something else (one list value object shared for all lists related properties)? -// if (hasRootNode.isDefined && !stringFormatter.isKnoraListIriStr(hasRootNode.get)) { -// throw BadRequestException(s"Invalid root node IRI is given.") -// } -// // If payload contains labels, they should not be empty -// if (labels.exists(_.isEmpty)) { -// throw BadRequestException(UPDATE_REQUEST_EMPTY_LABEL_ERROR) -// } -// -// if (position.exists(_ < -1)) { -// throw BadRequestException(INVALID_POSITION) -// } - def toJsValue: JsValue = changeListInfoApiRequestADMFormat.write(this) } diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 17f54e39da..979b3452b7 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -189,27 +189,8 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) } val labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v) - val comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) - val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( - id = maybeId, - projectIri, - name = maybeName, - labels, - comments - ) - - val createChildNodePayloadADM: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( - id = maybeId, - parentNodeIri = maybeParentNodeIri, - projectIri, - name = maybeName, - position = maybePosition, - labels, - comments = Some(comments) - ) - val requestMessage = for { requestingUser <- getUserADM(requestContext, featureFactoryConfig) @@ -224,6 +205,17 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) createRequest = if (apiRequest.parentNodeIri.isEmpty) { // No, create a new list with given information of its root node. + + val comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) + + val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( + id = maybeId, + projectIri, + name = maybeName, + labels, + comments + ) + ListCreateRequestADM( createRootNode = createRootNodePayloadADM, featureFactoryConfig = featureFactoryConfig, @@ -232,6 +224,24 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) ) } else { // Yes, create a new child and attach it to the parent node. + + // allows to omit comments / send empty comments creating child node + val maybeComments = if (apiRequest.comments.isEmpty) { + None + } else { + Some(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) + } + + val createChildNodePayloadADM: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( + id = maybeId, + parentNodeIri = maybeParentNodeIri, + projectIri, + name = maybeName, + position = maybePosition, + labels, + comments = maybeComments + ) + ListChildNodeCreateRequestADM( createChildNodeRequest = createChildNodePayloadADM, featureFactoryConfig = featureFactoryConfig, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 1905dd528b..1cce8fc056 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -155,11 +155,6 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } - val maybePosition: Option[Position] = apiRequest.position match { - case Some(value) => Some(Position.create(value).fold(e => throw e, v => v)) - case None => None - } - val projectIri = ProjectIRI.create(apiRequest.projectIri).fold(e => throw e, v => v) val createRootNodePayloadADM: ListCreatePayloadADM = ListCreatePayloadADM( @@ -391,6 +386,13 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) case None => None } + // allows to omit comments / send empty comments creating child node + val maybeComments = if (apiRequest.comments.isEmpty) { + None + } else { + Some(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) + } + val createChildNodeRequest: ChildNodeCreatePayloadADM = ChildNodeCreatePayloadADM( id = maybeId, parentNodeIri = maybeParentNodeIri, @@ -398,7 +400,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) name = maybeName, position = maybePosition, labels = Labels.create(apiRequest.labels).fold(e => throw e, v => v), - comments = Some(Comments.create(apiRequest.comments).fold(e => throw e, v => v)) + comments = maybeComments ) val requestMessage: Future[ListChildNodeCreateRequestADM] = for { From 7aaffcf540703e4aacbd8627369bcdee87deaa7d Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 28 Oct 2021 08:06:58 +0200 Subject: [PATCH 30/32] clenup --- .../valueObjects/ListsValueObjectsADM.scala | 5 -- .../responders/admin/ListsResponderADM.scala | 12 ++-- .../admin/lists/OldListsRouteADMFeature.scala | 2 +- .../OldListsRouteADMFeatureE2ESpec.scala | 2 - .../UpdateListItemsRouteADME2ESpec.scala | 66 +++++++++---------- .../ListsValueObjectsADMSpec.scala | 7 +- .../admin/ListsResponderADMSpec.scala | 2 - 7 files changed, 38 insertions(+), 58 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index 5326d521aa..e03053dd3e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -18,10 +18,6 @@ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtil import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import scala.util.{Failure, Success, Try} -//TODO: sprawdzic na koncu wszystkie czeki w messangerze czy poktrywaja sie tu i tak samo tresci bledow -//TODO: possible to somehow merge all IRI related value objects? what about diff exception messages -// either use below checks in route to throw custom exceptions for one IRI value object -// or bring these matches here /** * List ListIRI value object. @@ -60,7 +56,6 @@ object ProjectIRI { if (value.isEmpty) { Left(BadRequestException(PROJECT_IRI_MISSING_ERROR)) } else { - // TODO: nonEmpty vs isDefined ?? if (value.nonEmpty && !stringFormatter.isKnoraProjectIriStr(value)) { Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) } else { diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index d2d1efe2ec..a6cc2e7556 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -27,10 +27,7 @@ import org.knora.webapi.exceptions._ import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ -import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ - ChildNodeCreatePayloadADM, - ListCreatePayloadADM -} +import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.ChildNodeCreatePayloadADM import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectGetADM, ProjectIdentifierADM} import org.knora.webapi.messages.admin.responder.usersmessages._ @@ -855,7 +852,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde featureFactoryConfig: FeatureFactoryConfig ): Future[IRI] = { - println("ZZZZZ-createNode", createNodeRequest) +// println("ZZZZZ-createNode", createNodeRequest) val (id, parentNodeIri, projectIri, name, position) = createNodeRequest match { case parent: NodeCreatePayloadADM.ListCreatePayloadADM => @@ -953,7 +950,6 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde name ) _ = if (!projectUniqueNodeName) { -// TODO: all Option.get occurrences should be replaced by map val escapedName = name.get.value val unescapedName = stringFormatter.fromSparqlEncodedString(escapedName) throw BadRequestException( @@ -1051,7 +1047,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde apiRequestID: UUID ): Future[ListGetResponseADM] = { - println("XXXXX-listCreateRequestADM") +// println("XXXXX-listCreateRequestADM") /** * The actual task run with an IRI lock. @@ -1138,7 +1134,7 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde ): Future[NodeInfoGetResponseADM] = for { - _ <- Future(println("77777", nodeIri, changeNodeRequest.listIri)) +// _ <- Future(println("77777", nodeIri, changeNodeRequest.listIri)) // check if nodeIRI in path and payload match _ <- Future( diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 1cce8fc056..7abc158e20 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -165,7 +165,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) comments = Comments.create(apiRequest.comments).fold(e => throw e, v => v) ) - println("XXXXX", createRootNodePayloadADM) +// println("AAA-createList", createRootNodePayloadADM) val requestMessage: Future[ListCreateRequestADM] = for { requestingUser <- getUserADM( diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala index a007bf0bde..4c816c031a 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/OldListsRouteADMFeatureE2ESpec.scala @@ -107,8 +107,6 @@ class OldListsRouteADMFeatureE2ESpec Get(baseApiUrl + s"/admin/lists") ~> addCredentials(BasicHttpCredentials(rootCreds.email, rootCreds.password)) val response: HttpResponse = singleAwaitingRequest(request) -// println(s"response: ${response.toString}") - response.status should be(StatusCodes.OK) val lists: Seq[ListNodeInfoADM] = diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala index 4151add68f..d246460b2e 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/lists/UpdateListItemsRouteADME2ESpec.scala @@ -381,40 +381,38 @@ class UpdateListItemsRouteADME2ESpec ) } -// "delete child node comments" in { -//// this test should pass, but deleting comments for both root and child nodes are not working now using PUT and [] -//// TODO: implement DELETE method (only for child) -// val deleteNodeComments = -// s"""{ -// | "comments": [] -// |}""".stripMargin -// -// clientTestDataCollector.addFile( -// TestDataFileContent( -// filePath = TestDataFilePath( -// directoryPath = clientTestDataPath, -// filename = "update-childNode-comments-request", -// fileExtension = "json" -// ), -// text = deleteNodeComments -// ) -// ) -// -// val encodedListUrl = java.net.URLEncoder.encode(treeChildNode.id, "utf-8") -// -// val request = Put( -// baseApiUrl + s"/admin/lists/" + encodedListUrl + "/comments", -// HttpEntity(ContentTypes.`application/json`, deleteNodeComments) -// ) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) -// val response: HttpResponse = singleAwaitingRequest(request) -// -// response.status should be(StatusCodes.OK) -// -// val receivedNodeInfo: ListChildNodeInfoADM = -// AkkaHttpUtils.httpResponseToJson(response).fields("nodeinfo").convertTo[ListChildNodeInfoADM] -// val comments: Seq[StringLiteralV2] = receivedNodeInfo.comments.stringLiterals -// comments.size should be(0) -// } + "not delete child node comments by sending empty array" in { + val deleteNodeComments = + s"""{ + | "comments": [] + |}""".stripMargin + + clientTestDataCollector.addFile( + TestDataFileContent( + filePath = TestDataFilePath( + directoryPath = clientTestDataPath, + filename = "update-childNode-comments-request", + fileExtension = "json" + ), + text = deleteNodeComments + ) + ) + + val encodedListUrl = java.net.URLEncoder.encode(treeChildNode.id, "utf-8") + + val request = Put( + baseApiUrl + s"/admin/lists/" + encodedListUrl + "/comments", + HttpEntity(ContentTypes.`application/json`, deleteNodeComments) + ) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) + val response: HttpResponse = singleAwaitingRequest(request) + + response.status should be(StatusCodes.OK) + + val receivedNodeInfo: ListChildNodeInfoADM = + AkkaHttpUtils.httpResponseToJson(response).fields("nodeinfo").convertTo[ListChildNodeInfoADM] + val comments: Seq[StringLiteralV2] = receivedNodeInfo.comments.stringLiterals + comments.size should be(1) + } "not update the position of a node if given IRI is invalid" in { val parentIri = "http://rdfh.ch/lists/0001/notUsedList01" diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index 96882de2ae..b92226e5ed 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -56,8 +56,6 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using valid value" should { "return value object that value equals to the value used to its creation" in { -//// TODO: this probably doesn't make sense -// ListIRI.create(validListIri).map(_.value should equal(validListIri)) ListIRI.create(validListIri) should not equal Left(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) } } @@ -79,7 +77,6 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using valid value" should { "not throw BadRequestExceptions" in { -// ProjectIRI.create(validProjectIri).map(_.value should equal(validProjectIri)) ProjectIRI.create(validProjectIri) should not equal Left(BadRequestException(PROJECT_IRI_INVALID_ERROR)) } } @@ -95,7 +92,7 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using invalid value" should { "throw BadRequestException" in { -// TODO: should this: "\"It's invalid list name example\"" pass? +// TODO: should this: "\"It's invalid list name example\"" pass? Same for comments and labels ListName.create("\r") should equal(Left(BadRequestException(LIST_NAME_INVALID_ERROR))) } } @@ -132,7 +129,6 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using invalid value" should { "throw BadRequestException" in { - // TODO: should this: "\"It's invalid list name example\"" pass? Labels.create(invalidLabels) should equal(Left(BadRequestException(LABEL_INVALID_ERROR))) } } @@ -154,7 +150,6 @@ class ListsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { } "created using invalid value" should { "throw BadRequestException" in { - // TODO: should this: "\"It's invalid list name example\"" pass? Comments.create(invalidComments) should equal(Left(BadRequestException(COMMENT_INVALID_ERROR))) } } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index b3d8afa485..9581d1bce0 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -366,8 +366,6 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with apiRequestID = UUID.randomUUID ) - // log.debug(s"response: ${response.toString}") - val received: ChildNodeInfoGetResponseADM = expectMsgType[ChildNodeInfoGetResponseADM](timeout) val nodeInfo = received.nodeinfo From c1ea8f11313212940b5421756827753ee2c20c71 Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 29 Oct 2021 14:21:26 +0200 Subject: [PATCH 31/32] review fixes --- ...lADM.scala => ListsErrorMessagesADM.scala} | 2 +- .../listsmessages/ListsMessagesADM.scala | 41 +++++++++++++++---- .../valueObjects/ListsValueObjectsADM.scala | 2 +- .../listsmessages/ListsMessagesV2.scala | 11 +++-- .../responders/admin/ListsResponderADM.scala | 2 +- .../admin/lists/NewListsRouteADMFeature.scala | 2 +- .../admin/lists/OldListsRouteADMFeature.scala | 2 +- .../listsmessages/ListsMessagesADMSpec.scala | 2 +- .../ListsValueObjectsADMSpec.scala | 2 +- 9 files changed, 48 insertions(+), 18 deletions(-) rename webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/{ListsMessagesUtilADM.scala => ListsErrorMessagesADM.scala} (97%) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsErrorMessagesADM.scala similarity index 97% rename from webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala rename to webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsErrorMessagesADM.scala index 0ea5b96370..81e5ec16dd 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsErrorMessagesADM.scala @@ -5,7 +5,7 @@ package org.knora.webapi.messages.admin.responder.listsmessages -object ListsMessagesUtilADM { +object ListsErrorMessagesADM { val LIST_IRI_MISSING_ERROR = "List IRI cannot be empty." val LIST_IRI_INVALID_ERROR = "List IRI cannot be empty." val LIST_NODE_IRI_MISSING_ERROR = "List node IRI cannot be empty." diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 713e9e4ed9..36651d31e8 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -11,7 +11,7 @@ import org.knora.webapi._ import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ +import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM._ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.ChildNodeCreatePayloadADM import org.knora.webapi.messages.admin.responder.usersmessages._ import org.knora.webapi.messages.admin.responder.{KnoraRequestADM, KnoraResponseADM} @@ -764,7 +764,21 @@ case class ListChildNodeADM( position: Int, hasRootNode: IRI, children: Seq[ListChildNodeADM] -) extends ListNodeADM(id, name, labels, comments.get, children) { +) extends ListNodeADM( + id, + name, + labels, + comments = comments match { + case Some(value) => value + case None => StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) + }, + children + ) { + + private val maybeComments = comments match { + case Some(value) => Some(value) + case None => None + } /** * Sorts the whole hierarchy. @@ -776,7 +790,7 @@ case class ListChildNodeADM( id = id, name = name, labels = labels.sortByStringValue, - comments = comments.map(_.sortByStringValue), + comments = maybeComments, position = position, hasRootNode = hasRootNode, children = children.sortBy(_.position).map(_.sorted) @@ -789,14 +803,17 @@ case class ListChildNodeADM( val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance val unescapedLabels = stringFormatter.unescapeStringLiteralSeq(labels) - val unescapedComments = stringFormatter.unescapeStringLiteralSeq(comments.get) + val unescapedComments = comments match { + case Some(value) => Some(stringFormatter.unescapeStringLiteralSeq(value)) + case None => None + } val unescapedName: Option[String] = name match { - case None => None case Some(value) => Some(stringFormatter.fromSparqlEncodedString(value)) + case None => None } - copy(name = unescapedName, labels = unescapedLabels, comments = Some(unescapedComments)) + copy(name = unescapedName, labels = unescapedLabels, comments = unescapedComments) } /** @@ -817,7 +834,10 @@ case class ListChildNodeADM( * @return the comment in the preferred language. */ def getCommentInPreferredLanguage(userLang: String, fallbackLang: String): Option[String] = - comments.get.getPreferredLanguage(userLang, fallbackLang) + comments match { + case Some(value) => value.getPreferredLanguage(userLang, fallbackLang) + case None => None + } } /** @@ -1015,11 +1035,16 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with ) case child: ListChildNodeADM => + val maybeComments: StringLiteralSequenceV2 = child.comments match { + case Some(value) => value + case None => StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) + } + JsObject( "id" -> child.id.toJson, "name" -> child.name.toJson, "labels" -> JsArray(child.labels.stringLiterals.map(_.toJson)), - "comments" -> JsArray(child.comments.get.stringLiterals.map(_.toJson)), + "comments" -> JsArray(maybeComments.stringLiterals.map(_.toJson)), "position" -> child.position.toJson, "hasRootNode" -> child.hasRootNode.toJson, "children" -> JsArray(child.children.map(write).toVector) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index e03053dd3e..c8508597a2 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -2,7 +2,7 @@ package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ +import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM.{ COMMENT_INVALID_ERROR, COMMENT_MISSING_ERROR, INVALID_POSITION, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala index 06e625e76a..a6224ea1b8 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala @@ -10,7 +10,7 @@ import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserADM -import org.knora.webapi.messages.store.triplestoremessages.StringLiteralSequenceV2 +import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} import org.knora.webapi.messages.util.rdf import org.knora.webapi.messages.util.rdf._ import org.knora.webapi.messages.v2.responder.{KnoraJsonLDResponseV2, KnoraRequestV2} @@ -89,8 +89,13 @@ case class ListGetResponseV2(list: ListADM, userLang: String, fallbackLang: Stri val label: Map[IRI, JsonLDString] = makeMapIriToJSONLDString(OntologyConstants.Rdfs.Label, node.labels, userLang, fallbackLang) - val comment: Map[IRI, JsonLDString] = - makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, node.comments.get, userLang, fallbackLang) + val comment: Map[IRI, JsonLDString] = { + val maybeComment = node.comments match { + case Some(value) => value + case None => StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) + } + makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, maybeComment, userLang, fallbackLang) + } val position: Map[IRI, JsonLDInt] = Map( OntologyConstants.KnoraBase.ListNodePosition.toSmartIri.toOntologySchema(ApiV2Complex).toString -> JsonLDInt( diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index 24bebf8d9d..9be2342052 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -12,7 +12,7 @@ import org.knora.webapi._ import org.knora.webapi.exceptions._ import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.IriConversions._ -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ +import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM._ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.ChildNodeCreatePayloadADM import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectGetADM, ProjectIdentifierADM} diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 9902dfe94e..67a9b79e43 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -14,7 +14,7 @@ import javax.ws.rs.Path import org.knora.webapi.IRI import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.LIST_CREATE_PERMISSION_ERROR +import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM.LIST_CREATE_PERMISSION_ERROR import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.{ ChildNodeCreatePayloadADM, ListCreatePayloadADM diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 085353a4a6..dece508ad4 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -14,7 +14,7 @@ import javax.ws.rs.Path import org.knora.webapi.IRI import org.knora.webapi.exceptions.{BadRequestException, ForbiddenException} import org.knora.webapi.feature.{Feature, FeatureFactoryConfig} -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ +import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM.{ LIST_CREATE_PERMISSION_ERROR, LIST_NODE_CREATE_PERMISSION_ERROR } diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index f77842c32c..fdd2827ccc 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -9,7 +9,7 @@ import java.util.UUID import com.typesafe.config.ConfigFactory import org.knora.webapi.CoreSpec import org.knora.webapi.exceptions.BadRequestException -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ +import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM._ import org.knora.webapi.messages.admin.responder.listsmessages.NodeCreatePayloadADM.ChildNodeCreatePayloadADM import org.knora.webapi.messages.admin.responder.valueObjects.{Comments, Labels, ListIRI, ProjectIRI, Position} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralSequenceV2, StringLiteralV2} diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala index b92226e5ed..3b314ec0f4 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADMSpec.scala @@ -20,7 +20,7 @@ package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.exceptions.BadRequestException -import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM.{ +import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM.{ COMMENT_INVALID_ERROR, COMMENT_MISSING_ERROR, INVALID_POSITION, From 34c555c04025b6ec452758ab799bc6bf96c0b0bb Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Fri, 29 Oct 2021 15:02:15 +0200 Subject: [PATCH 32/32] minor improvements --- .../listsmessages/ListsMessagesADM.scala | 24 +++++++------------ .../listsmessages/ListsMessagesV2.scala | 12 +++++----- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 36651d31e8..747db919b6 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -768,18 +768,10 @@ case class ListChildNodeADM( id, name, labels, - comments = comments match { - case Some(value) => value - case None => StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) - }, + comments = comments.getOrElse(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), children ) { - private val maybeComments = comments match { - case Some(value) => Some(value) - case None => None - } - /** * Sorts the whole hierarchy. * @@ -790,7 +782,7 @@ case class ListChildNodeADM( id = id, name = name, labels = labels.sortByStringValue, - comments = maybeComments, + comments = comments, position = position, hasRootNode = hasRootNode, children = children.sortBy(_.position).map(_.sorted) @@ -1035,16 +1027,16 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with ) case child: ListChildNodeADM => - val maybeComments: StringLiteralSequenceV2 = child.comments match { - case Some(value) => value - case None => StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) - } - JsObject( "id" -> child.id.toJson, "name" -> child.name.toJson, "labels" -> JsArray(child.labels.stringLiterals.map(_.toJson)), - "comments" -> JsArray(maybeComments.stringLiterals.map(_.toJson)), + "comments" -> JsArray( + child.comments + .getOrElse(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])) + .stringLiterals + .map(_.toJson) + ), "position" -> child.position.toJson, "hasRootNode" -> child.hasRootNode.toJson, "children" -> JsArray(child.children.map(write).toVector) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala index a6224ea1b8..dcda2c4457 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/listsmessages/ListsMessagesV2.scala @@ -86,15 +86,15 @@ case class ListGetResponseV2(list: ListADM, userLang: String, fallbackLang: Stri * @return a [[JsonLDObject]] representing the node. */ def makeNode(node: ListChildNodeADM): JsonLDObject = { - val label: Map[IRI, JsonLDString] = makeMapIriToJSONLDString(OntologyConstants.Rdfs.Label, node.labels, userLang, fallbackLang) val comment: Map[IRI, JsonLDString] = { - val maybeComment = node.comments match { - case Some(value) => value - case None => StringLiteralSequenceV2(Vector.empty[StringLiteralV2]) - } - makeMapIriToJSONLDString(OntologyConstants.Rdfs.Comment, maybeComment, userLang, fallbackLang) + makeMapIriToJSONLDString( + OntologyConstants.Rdfs.Comment, + node.comments.getOrElse(StringLiteralSequenceV2(Vector.empty[StringLiteralV2])), + userLang, + fallbackLang + ) } val position: Map[IRI, JsonLDInt] = Map(