Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(resource-metadata): return resource metadata after metadata upda…
…te request (DSP-1828) (#1893)

* change response for update resource metadata request

* Add new last modification date to response

* add e2e tests

* update documentation

* remove option from lastModificationDate
  • Loading branch information
irinaschubert committed Aug 2, 2021
1 parent 3e3a3ce commit a4e878a
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 13 deletions.
2 changes: 1 addition & 1 deletion docs/03-apis/api-v2/editing-resources.md
Expand Up @@ -298,7 +298,7 @@ date, you will get an HTTP 409 (Conflict) error.
If you submit a `knora-api:newModificationDate` that is earlier than the resource's `knora-api:lastModificationDate`,
you will get an HTTP 400 (Bad Request) error.

A successful response is an HTTP 200 (OK) status containing a confirmation message.
A successful response is an HTTP 200 (OK) status containing the resource's metadata.

## Deleting a Resource

Expand Down
Expand Up @@ -21,7 +21,6 @@ package org.knora.webapi.messages.v2.responder.resourcemessages

import java.time.Instant
import java.util.UUID

import akka.actor.ActorRef
import akka.event.LoggingAdapter
import akka.pattern._
Expand Down Expand Up @@ -897,6 +896,86 @@ object UpdateResourceMetadataRequestV2 extends KnoraJsonLDRequestReaderV2[Update
}
}

/**
* Represents a response after updating a resource's metadata.
*
* @param resourceIri the IRI of the resource.
* @param resourceClassIri the IRI of the resource class.
* @param lastModificationDate the resource's last modification date.
* @param maybeLabel the resource's new `rdfs:label`, if any.
* @param maybePermissions the resource's new permissions, if any.
* @param featureFactoryConfig the feature factory configuration.
*/
case class UpdateResourceMetadataResponseV2(resourceIri: IRI,
resourceClassIri: SmartIri,
lastModificationDate: Instant,
maybeLabel: Option[String] = None,
maybePermissions: Option[String] = None,
featureFactoryConfig: FeatureFactoryConfig)
extends KnoraJsonLDResponseV2 {

/**
* Converts the response to a data structure that can be used to generate JSON-LD.
*
* @param targetSchema the Knora API schema to be used in the JSON-LD document.
* @return a [[JsonLDDocument]] representing the response.
*/
override protected def toJsonLDDocument(targetSchema: ApiV2Schema,
settings: KnoraSettingsImpl,
schemaOptions: Set[SchemaOption]): JsonLDDocument = {

implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance

// Make the knora-api prefix for the target schema.

val knoraApiPrefixExpansion: IRI = targetSchema match {
case ApiV2Simple => OntologyConstants.KnoraApiV2Simple.KnoraApiV2PrefixExpansion
case ApiV2Complex => OntologyConstants.KnoraApiV2Complex.KnoraApiV2PrefixExpansion
}

// Make the JSON-LD document.

val context: JsonLDObject = JsonLDUtil.makeContext(
fixedPrefixes = Map(
"rdf" -> OntologyConstants.Rdf.RdfPrefixExpansion,
"rdfs" -> OntologyConstants.Rdfs.RdfsPrefixExpansion,
"xsd" -> OntologyConstants.Xsd.XsdPrefixExpansion,
OntologyConstants.KnoraApi.KnoraApiOntologyLabel -> knoraApiPrefixExpansion
)
)

val label_map = maybeLabel match {
case Some(maybeLabel) => Map(OntologyConstants.Rdfs.Label -> JsonLDString(maybeLabel))
case None => Map.empty[String, JsonLDValue]
}

val lastModificationDate_map =
Map(
OntologyConstants.KnoraApiV2Complex.LastModificationDate -> JsonLDUtil.datatypeValueToJsonLDObject(
value = lastModificationDate.toString,
datatype = OntologyConstants.Xsd.DateTimeStamp.toSmartIri
))

val permissions_map = maybePermissions match {
case Some(maybePermissions) =>
Map(OntologyConstants.KnoraApiV2Complex.HasPermissions -> JsonLDString(maybePermissions))
case None => Map.empty[String, JsonLDValue]
}

val resourceIri_resourceClassIri_map =
Map(
OntologyConstants.KnoraApiV2Complex.ResourceIri -> JsonLDString(resourceIri),
OntologyConstants.KnoraApiV2Complex.ResourceClassIri -> JsonLDString(resourceClassIri.toString)
)

val body = JsonLDObject(
resourceIri_resourceClassIri_map ++ label_map ++ lastModificationDate_map ++ permissions_map)

JsonLDDocument(body = body, context = context)

}
}

/**
* Represents a request to mark a resource as deleted or to erase it from the triplestore.
*
Expand Down
Expand Up @@ -364,11 +364,11 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt
* Updates a resources metadata.
*
* @param updateResourceMetadataRequestV2 the update request.
* @return a [[SuccessResponseV2]].
* @return a [[UpdateResourceMetadataResponseV2]].
*/
private def updateResourceMetadataV2(
updateResourceMetadataRequestV2: UpdateResourceMetadataRequestV2): Future[SuccessResponseV2] = {
def makeTaskFuture: Future[SuccessResponseV2] = {
updateResourceMetadataRequestV2: UpdateResourceMetadataRequestV2): Future[UpdateResourceMetadataResponseV2] = {
def makeTaskFuture: Future[UpdateResourceMetadataResponseV2] = {
for {
// Get the metadata of the resource to be updated.
resourcesSeq: ReadResourcesSequenceV2 <- getResourcePreviewV2(
Expand Down Expand Up @@ -487,7 +487,15 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt

case None => FastFuture.successful(())
}
} yield SuccessResponseV2("Resource metadata updated")
} yield
UpdateResourceMetadataResponseV2(
resourceIri = updateResourceMetadataRequestV2.resourceIri,
resourceClassIri = updateResourceMetadataRequestV2.resourceClassIri,
maybeLabel = updateResourceMetadataRequestV2.maybeLabel,
maybePermissions = updateResourceMetadataRequestV2.maybePermissions,
lastModificationDate = newModificationDate,
featureFactoryConfig = updateResourceMetadataRequestV2.featureFactoryConfig
)
}

for {
Expand Down
Expand Up @@ -22,7 +22,6 @@ package org.knora.webapi.e2e.v2
import java.net.URLEncoder
import java.nio.file.Paths
import java.time.Instant

import akka.actor.ActorSystem
import akka.http.scaladsl.model.headers.{Accept, BasicHttpCredentials}
import akka.http.scaladsl.model.{HttpEntity, HttpResponse, MediaRange, StatusCodes}
Expand Down Expand Up @@ -90,6 +89,27 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
| }
|}""".stripMargin

private def updateResourceMetadataResponse(newLastModificationDate: Instant,
maybeNewLabel: String,
resourceIri: String,
maybeNewPermissions: String): String =
s"""{
| "knora-api:lastModificationDate": {
| "@value": "$newLastModificationDate",
| "@type": "xsd:dateTimeStamp"
| },
| "rdfs:label": "$maybeNewLabel",
| "knora-api:resourceIri": "$resourceIri",
| "knora-api:hasPermissions": "$maybeNewPermissions",
| "knora-api:resourceClassIri": "http://0.0.0.0:3333/ontology/0001/anything/v2#Thing",
| "@context": {
| "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
| "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
| "xsd": "http://www.w3.org/2001/XMLSchema#",
| "knora-api": "http://api.knora.org/ontology/knora-api/v2#"
| }
|}""".stripMargin

"The resources v2 endpoint" should {
"perform a resource request for the book 'Reise ins Heilige Land' using the complex schema in JSON-LD" in {
val request = Get(s"$baseApiUrl/v2/resources/${URLEncoder.encode("http://rdfh.ch/0803/2a6221216701", "UTF-8")}")
Expand Down Expand Up @@ -1512,7 +1532,12 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
val updateResponse: HttpResponse = singleAwaitingRequest(updateRequest)
val updateResponseAsString: String = responseToString(updateResponse)
assert(updateResponse.status == StatusCodes.OK, updateResponseAsString)
assert(JsonParser(updateResponseAsString) == JsonParser(successResponse("Resource metadata updated")))
assert(
JsonParser(updateResponseAsString) == JsonParser(
updateResourceMetadataResponse(resourceIri = resourceIri,
maybeNewLabel = newLabel,
newLastModificationDate = newModificationDate,
maybeNewPermissions = newPermissions)))

clientTestDataCollector.addFile(
TestDataFileContent(
Expand Down Expand Up @@ -1594,7 +1619,12 @@ class ResourcesRouteV2E2ESpec extends E2ESpec(ResourcesRouteV2E2ESpec.config) {
val updateResponse: HttpResponse = singleAwaitingRequest(updateRequest)
val updateResponseAsString: String = responseToString(updateResponse)
assert(updateResponse.status == StatusCodes.OK, updateResponseAsString)
assert(JsonParser(updateResponseAsString) == JsonParser(successResponse("Resource metadata updated")))
assert(
JsonParser(updateResponseAsString) == JsonParser(
updateResourceMetadataResponse(resourceIri = resourceIri,
maybeNewLabel = newLabel,
newLastModificationDate = newModificationDate,
maybeNewPermissions = newPermissions)))

val previewRequest = Get(s"$baseApiUrl/v2/resourcespreview/${URLEncoder.encode(resourceIri, "UTF-8")}") ~> addCredentials(
BasicHttpCredentials(anythingUserEmail, password))
Expand Down
Expand Up @@ -1762,7 +1762,7 @@ class ResourcesResponderV2Spec extends CoreSpec() with ImplicitSender {

responderManager ! updateRequest

expectMsgType[SuccessResponseV2](timeout)
expectMsgType[UpdateResourceMetadataResponseV2](timeout)

// Get the resource from the triplestore and check it.

Expand Down Expand Up @@ -1825,7 +1825,7 @@ class ResourcesResponderV2Spec extends CoreSpec() with ImplicitSender {

responderManager ! updateRequest

expectMsgType[SuccessResponseV2](timeout)
expectMsgType[UpdateResourceMetadataResponseV2](timeout)

// Get the resource from the triplestore and check it.

Expand Down Expand Up @@ -1869,7 +1869,7 @@ class ResourcesResponderV2Spec extends CoreSpec() with ImplicitSender {

responderManager ! updateRequest

expectMsgType[SuccessResponseV2](timeout)
expectMsgType[UpdateResourceMetadataResponseV2](timeout)

// Get the resource from the triplestore and check it.

Expand Down Expand Up @@ -2680,7 +2680,7 @@ class ResourcesResponderV2Spec extends CoreSpec() with ImplicitSender {
apiRequestID = UUID.randomUUID
)

expectMsgType[SuccessResponseV2](timeout)
expectMsgType[UpdateResourceMetadataResponseV2](timeout)

responderManager ! ResourceHistoryEventsGetRequestV2(
resourceIri = resourceIri,
Expand Down

0 comments on commit a4e878a

Please sign in to comment.