Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api-v2): Return events describing version history of resources and values of a project ordered by data (DSP-1528) #1844

Merged
merged 36 commits into from May 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
58756c9
feature(api-v2): route to get history of resources within project + m…
SepidehAlassi Apr 14, 2021
594138f
feat(api-v2): add templates for getting all resources of a project
SepidehAlassi Apr 14, 2021
8954644
refactor(api-v2): rename twirl templates for getting resources of a p…
SepidehAlassi Apr 14, 2021
ea8f33b
test(api-v2): tests for returning resource IRIs of a project
SepidehAlassi Apr 14, 2021
9143a2b
fix(application.conf): increase TCP connecting-timeout
SepidehAlassi Apr 14, 2021
6686d7d
feat (api-v2): return version history of all resources in a project
SepidehAlassi Apr 15, 2021
a45392e
feat(api-v2): get full representation of each resource in each time s…
SepidehAlassi Apr 16, 2021
f6179cb
feat(api-v2): model event for response
SepidehAlassi Apr 16, 2021
575ad94
feat (histEvent): return a createResource event for each resource wit…
SepidehAlassi Apr 21, 2021
2641bad
fix (historyEvents): fix test
SepidehAlassi Apr 22, 2021
74beac7
feat(historyEvents): extract full value histories
SepidehAlassi Apr 23, 2021
4e617dc
feat (historyEvents): return create/update/delete events for values o…
SepidehAlassi Apr 23, 2021
3d0ffa7
feat (historyEvents): update Permission event
SepidehAlassi Apr 26, 2021
1faa04a
fix (historyEvent) use isAfter method of instant
SepidehAlassi Apr 26, 2021
ce6bebe
Merge branch 'main' into wip/DSP-1528-getResourcesOfProjectOrderedByDate
SepidehAlassi Apr 26, 2021
0bfdfd4
fix(testData): creation date of the resource a-thing-picture cannot b…
SepidehAlassi Apr 26, 2021
490ec70
feat(historyEvents): return all resource and value histories of a pro…
SepidehAlassi Apr 26, 2021
1a5ae0b
feat (historyEvents): sort events by date
SepidehAlassi Apr 26, 2021
b21322e
feat(historyEvent) serialize project history response as JSONLD
SepidehAlassi Apr 27, 2021
3977f90
feat(historyEvent): return deleted values as part of full representat…
SepidehAlassi Apr 27, 2021
d6222a1
test(historyEvent): e2e test
SepidehAlassi Apr 27, 2021
6cb8c3b
test (historyEvent): test for serialization of event metadata
SepidehAlassi Apr 28, 2021
5ccde6a
test (historyEvents): e2e test
SepidehAlassi Apr 28, 2021
220307e
feat(historyEvent): serialize value contents
SepidehAlassi Apr 28, 2021
5fff986
fix (historyEvent): fix the failing test
SepidehAlassi Apr 29, 2021
cfa35b7
refactor (historyEvent): some refactoring and clean up
SepidehAlassi Apr 29, 2021
c270369
docs(historyEvent): add documentation
SepidehAlassi Apr 29, 2021
4275ee5
fix (historyEvents): fix the failing test
SepidehAlassi Apr 29, 2021
a8e934c
fix (historyEvent): fix the remaining wrong dates
SepidehAlassi Apr 29, 2021
b2bfd6d
refactor(historyEvents): some restructuring
SepidehAlassi Apr 30, 2021
b6f6001
Merge branch 'main' into wip/DSP-1528-getResourcesOfProjectOrderedByDate
May 3, 2021
4cdf684
feat(historyEvent): create an event for a deleted resource
SepidehAlassi May 3, 2021
a94431f
Merge branch 'wip/DSP-1528-getResourcesOfProjectOrderedByDate' of htt…
SepidehAlassi May 3, 2021
70224be
feat (historyEvent): return delete comment when getting the full repr…
SepidehAlassi May 3, 2021
9e92bb6
fix (historyEvent): fix the build problem
SepidehAlassi May 3, 2021
26321fd
refactor (docs): clean up documentation
SepidehAlassi May 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/03-apis/api-v2/editing-resources.md
Expand Up @@ -277,7 +277,7 @@ Here is an example:
"knora-api:lastModificationDate" : {
"@type" : "xsd:dateTimeStamp",
"@value" : "2017-11-20T15:55:17Z"
}
},
"knora-api:newModificationDate" : {
"@type" : "xsd:dateTimeStamp",
"@value" : "2018-12-21T16:56:18Z"
Expand Down
130 changes: 130 additions & 0 deletions docs/03-apis/api-v2/reading-and-searching-resources.md
Expand Up @@ -558,3 +558,133 @@ The `orderByProperty` parameter is optional; if it is not supplied, resources wi
be sorted alphabetically by resource IRI (an arbitrary but consistent order).
The value of `page` is a 0-based integer page number. Paging works as it does
in [Gravsearch](query-language.md)).

### Get the Version History of Resources and Values of a Project

To get a list of the changes that have been made to resources and values of a project since their creation ordered by date
use this route:

```
HTTP GET to http://host/v2/resources/projectHistory/projectIRI
```

The project IRI must be URL-encoded. The response is a list of events describing changes made to the resource and its values,
in chronological order. Each entry has the properties:
`knora-api:eventType` (the type of the operation performed on a specific date. The operation can be either
`createResource`, `deleteResource`, `createValue`, `updateValueContent`, `updateValuePermissions`, or `deleteValue`.),
`knora-api:versionDate` (the date when the change was made),
`knora-api:author` (the IRI of the user who made the change),
`knora-api:eventBody` (the information necessary to make the same request). For example:

```jsonld
{
"@graph" : [
{
"knora-api:eventType": "createResource",
"knora-api:author": {
"@id": "http://rdfh.ch/users/9XBCrDV3SRa7kS1WwynB4Q"
},
"knora-api:eventBody": {
"rdfs:label": "A thing with version history",
"knora-api:resourceIri": "http://rdfh.ch/0001/thing-with-history",
"knora-api:resourceClassIri": "http://www.knora.org/ontology/0001/anything#Thing",
"knora-api:hasPermissions": "CR knora-admin:Creator|M knora-admin:ProjectMember|V knora-admin:UnknownUser",
"knora-api:creationDate": {
"@value": "2019-02-08T15:05:10Z",
"@type": "xsd:dateTimeStamp"
},
"knora-api:attachedToProject": {
"@id": "http://rdfh.ch/projects/0001"
}
},
"knora-api:versionDate": {
"@value": "2019-02-08T15:05:10Z",
"@type": "xsd:dateTimeStamp"
}
},
{
"knora-api:eventType": "createValue",
"knora-api:author": {
"@id": "http://rdfh.ch/users/9XBCrDV3SRa7kS1WwynB4Q"
},
"knora-api:eventBody": {
"knora-api:resourceIri": "http://rdfh.ch/0001/thing-with-history",
"knora-api:resourceClassIri": "http://www.knora.org/ontology/0001/anything#Thing",
"knora-api:valueCreationDate": {
"@value": "2019-02-10T10:30:10Z",
"@type": "xsd:dateTimeStamp"
},
"knora-api:valueHasUUID": "IZGOjVqxTfSNO4ieKyp0SA",
"knora-api:hasPermissions": "V knora-admin:UnknownUser|M knora-admin:ProjectMember",
"@type": "knora-base:LinkValue",
"http://www.knora.org/ontology/0001/anything#hasOtherThingValue": {
"knora-api:linkValueHasTargetIri": {
"@id": "http://rdfh.ch/0001/2qMtTWvVRXWMBcRNlduvCQ"
}
},
"rdf:Property": "http://www.knora.org/ontology/0001/anything#hasOtherThingValue",
"@id": "http://rdfh.ch/0001/thing-with-history/values/3a"
},
"knora-api:versionDate": {
"@value": "2019-02-10T10:30:10Z",
"@type": "xsd:dateTimeStamp"
}
},
{
"knora-api:eventType": "updateValueContent",
"knora-api:author": {
"@id": "http://rdfh.ch/users/BhkfBc3hTeS_IDo-JgXRbQ"
},
"knora-api:eventBody": {
"knora-api:resourceIri": "http://rdfh.ch/0001/thing-with-history",
"knora-api:resourceClassIri": "http://www.knora.org/ontology/0001/anything#Thing"
"http://www.knora.org/ontology/0001/anything#hasText": {
"knora-api:valueAsString": "two"
},
"knora-api:valueCreationDate": {
"@value": "2019-02-11T10:05:10Z",
"@type": "xsd:dateTimeStamp"
},
"knora-base:previousValue": "http://rdfh.ch/0001/thing-with-history/values/2a",
"knora-api:valueHasUUID": "W5fm67e0QDWxRZumcXcs6g",
"@type": "knora-base:TextValue",
"rdf:Property": "http://www.knora.org/ontology/0001/anything#hasText",
"@id": "http://rdfh.ch/0001/thing-with-history/values/2b"
},
"knora-api:versionDate": {
"@value": "2019-02-11T10:05:10Z",
"@type": "xsd:dateTimeStamp"
}
},
{
"knora-api:eventType": "deleteValue",
"knora-api:author": {
"@id": "http://rdfh.ch/users/9XBCrDV3SRa7kS1WwynB4Q"
},
"knora-api:eventBody": {
"knora-api:resourceIri": "http://rdfh.ch/0001/thing-with-history",
"knora-api:resourceClassIri": "http://www.knora.org/ontology/0001/anything#Thing",
"knora-base:previousValue": "http://rdfh.ch/0001/thing-with-history/values/3a",
"knora-api:deleteDate": {
"@type": "xsd:dateTimeStamp",
"@value": "2019-02-13T09:00:10Z"
},
"knora-api:isDeleted": true,
"@type": "knora-base:LinkValue",
"rdf:Property": "http://www.knora.org/ontology/0001/anything#hasOtherThingValue",
"@id": "http://rdfh.ch/0001/thing-with-history/values/3b"
},
"knora-api:versionDate": {
"@value": "2019-02-13T09:00:10Z",
"@type": "xsd:dateTimeStamp"
}
}
],
"@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#"
}
}
```
5 changes: 3 additions & 2 deletions test_data/all_data/anything-data.ttl
Expand Up @@ -711,7 +711,7 @@
knora-base:attachedToProject <http://rdfh.ch/projects/0001>;
rdfs:label "A thing with a picture";
knora-base:hasPermissions "CR knora-admin:Creator|M knora-admin:ProjectMember|RV knora-admin:UnknownUser";
knora-base:creationDate "2016-03-02T15:05:10Z"^^xsd:dateTime;
knora-base:creationDate "2011-03-02T15:05:10Z"^^xsd:dateTime;
knora-base:hasStillImageFileValue <http://rdfh.ch/0001/a-thing-picture/values/goZ7JFRNSeqF-dNxsqAS7Q> .

<http://rdfh.ch/0001/a-thing-picture/values/goZ7JFRNSeqF-dNxsqAS7Q> a knora-base:StillImageFileValue;
Expand Down Expand Up @@ -1716,7 +1716,8 @@
anything:hasInteger <http://rdfh.ch/0001/XTxSMt0ySraVmwXD-bD2wQ/values/PVPAa37xR--K_wxQwlvSsg>;
rdfs:label "deleted thing";
knora-base:isDeleted true;
knora-base:deleteDate "2020-04-07T14:59:28.960124Z"^^xsd:dateTime .
knora-base:deleteDate "2020-04-07T14:59:28.960124Z"^^xsd:dateTime ;
knora-base:deleteComment "a comment for the deleted thing."^^xsd:string .

<http://rdfh.ch/0001/PHbbrEsVR32q5D_ioKt6pA/values/7BIm9QAiQqKixcgXDWf12Q> a knora-base:IntValue;
knora-base:attachedToUser <http://rdfh.ch/users/9XBCrDV3SRa7kS1WwynB4Q>;
Expand Down
4 changes: 2 additions & 2 deletions test_data/resourcesR2RV2/ThingWithPicture.jsonld
Expand Up @@ -25,15 +25,15 @@
},
"rdfs:label": "A thing with a picture",
"knora-api:versionArkUrl": {
"@value": "http://0.0.0.0:3336/ark:/72163/1/0001/a=thing=picture0.20160302T150510Z",
"@value": "http://0.0.0.0:3336/ark:/72163/1/0001/a=thing=picture0.20110302T150510Z",
"@type": "xsd:anyURI"
},
"knora-api:attachedToProject": {
"@id": "http://rdfh.ch/projects/0001"
},
"knora-api:userHasPermission": "RV",
"knora-api:creationDate": {
"@value": "2016-03-02T15:05:10Z",
"@value": "2011-03-02T15:05:10Z",
"@type": "xsd:dateTimeStamp"
},
"knora-api:attachedToUser": {
Expand Down
Expand Up @@ -39,15 +39,15 @@
"@id": "http://rdfh.ch/0001/a-thing-picture/values/goZ7JFRNSeqF-dNxsqAS7Q"
},
"knora-api:versionArkUrl": {
"@value": "http://0.0.0.0:3336/ark:/72163/1/0001/a=thing=picture0.20160302T150510Z",
"@value": "http://0.0.0.0:3336/ark:/72163/1/0001/a=thing=picture0.20110302T150510Z",
"@type": "xsd:anyURI"
},
"knora-api:attachedToProject": {
"@id": "http://rdfh.ch/projects/0001"
},
"knora-api:userHasPermission": "CR",
"knora-api:creationDate": {
"@value": "2016-03-02T15:05:10Z",
"@value": "2011-03-02T15:05:10Z",
"@type": "xsd:dateTimeStamp"
},
"knora-api:attachedToUser": {
Expand Down
Expand Up @@ -735,6 +735,10 @@ object OntologyConstants {
val Result: IRI = KnoraApiV2PrefixExpansion + "result"
val Error: IRI = KnoraApiV2PrefixExpansion + "error"
val MayHaveMoreResults: IRI = KnoraApiV2PrefixExpansion + "mayHaveMoreResults"
val EventType: IRI = KnoraApiV2PrefixExpansion + "eventType"
val EventBody: IRI = KnoraApiV2PrefixExpansion + "eventBody"
val ResourceClassIri: IRI = KnoraApiV2PrefixExpansion + "resourceClassIri"
val ResourceIri: IRI = KnoraApiV2PrefixExpansion + "resourceIri"

val IsShared: IRI = KnoraApiV2PrefixExpansion + "isShared"
val IsBuiltIn: IRI = KnoraApiV2PrefixExpansion + "isBuiltIn"
Expand Down
Expand Up @@ -1419,20 +1419,24 @@ object ConstructResponseUtilV2 {
timeout: Timeout,
executionContext: ExecutionContext): Future[ReadResourceV2] = {
def getDeletionInfo(rdfData: RdfData): Option[DeletionInfo] = {
val isDeleted: Boolean = rdfData.requireBooleanObject(OntologyConstants.KnoraBase.IsDeleted.toSmartIri)

if (isDeleted) {
val deleteDate = rdfData.requireDateTimeObject(OntologyConstants.KnoraBase.DeleteDate.toSmartIri)
val maybeDeleteComment = rdfData.maybeStringObject(OntologyConstants.KnoraBase.DeleteComment.toSmartIri)

Some(
DeletionInfo(
deleteDate = deleteDate,
maybeDeleteComment = maybeDeleteComment
)
)
} else {
None
val mayHaveDeletedStatements: Option[Boolean] =
rdfData.maybeBooleanObject(OntologyConstants.KnoraBase.IsDeleted.toSmartIri)
mayHaveDeletedStatements match {
case Some(isDeleted: Boolean) =>
if (isDeleted) {
val deleteDate = rdfData.requireDateTimeObject(OntologyConstants.KnoraBase.DeleteDate.toSmartIri)
val maybeDeleteComment = rdfData.maybeStringObject(OntologyConstants.KnoraBase.DeleteComment.toSmartIri)

Some(
DeletionInfo(
deleteDate = deleteDate,
maybeDeleteComment = maybeDeleteComment
)
)
} else {
None
}
case _ => None
}
}

Expand Down