diff --git a/src/main/java/edu/kit/scc/dem/wapsrv/service/AnnotationServiceImpl.java b/src/main/java/edu/kit/scc/dem/wapsrv/service/AnnotationServiceImpl.java index db64153..5c85a62 100644 --- a/src/main/java/edu/kit/scc/dem/wapsrv/service/AnnotationServiceImpl.java +++ b/src/main/java/edu/kit/scc/dem/wapsrv/service/AnnotationServiceImpl.java @@ -57,6 +57,20 @@ public class AnnotationServiceImpl extends AbstractWapService implements Annotat @Autowired private EtagFactory etagFactory; + /** + * Spec: WAP 5.3 Update an Existing Annotation + * + * @param iri + * The IRI of the annotation + * @param etag + * The ETag associated with the annotation state known to the client + * @param rawAnnotation + * A String representation of the Annotation + * @param format + * The data format used + * @return the updated annotation + * @throws WapException on error encountered during update + */ @Override public Annotation putAnnotation(final String iri, final String etag, String rawAnnotation, Format format) throws WapException{ @@ -82,12 +96,16 @@ public Annotation putAnnotation(final String iri, final String etag, String rawA if(!iri.equals(newAnnotation.getIriString())){ throw new UnallowedPropertyChangeException("The IRI cannot change with a PUT requests"); } + /** + * Servers SHOULD reject update requests that modify the values of the canonical or via properties, + * if they have been already set + */ // Check if no forbidden field has been changed canonical (there is only one) - if(!existingAnnotation.isPropertyEqual(newAnnotation, AnnoVocab.canonical)){ + if(existingAnnotation.hasProperty(AnnoVocab.canonical) && !existingAnnotation.isPropertyEqual(newAnnotation, AnnoVocab.canonical)){ throw new UnallowedPropertyChangeException("canonical property cannot change"); } // Check via (there may be more) - if(!existingAnnotation.isPropertyWithMultipleValuesEqual(newAnnotation, AnnoVocab.via)){ + if(existingAnnotation.hasProperty(AnnoVocab.via) && !existingAnnotation.isPropertyWithMultipleValuesEqual(newAnnotation, AnnoVocab.via)){ throw new UnallowedPropertyChangeException("via properties cannot change"); } String oldEtag = etag; diff --git a/src/main/resources/testdata/annotations/example0.jsonld b/src/main/resources/testdata/annotations/example0.jsonld new file mode 100644 index 0000000..8dc51cd --- /dev/null +++ b/src/main/resources/testdata/annotations/example0.jsonld @@ -0,0 +1,6 @@ +{ + "@context": "http://www.w3.org/ns/anno.jsonld", + "type": "Annotation", + "body": "http://example.org/post1", + "target": "http://example.com/page1" +} diff --git a/src/test/java/edu/kit/scc/dem/wapsrv/testsrest/AnnotationRestTest.java b/src/test/java/edu/kit/scc/dem/wapsrv/testsrest/AnnotationRestTest.java index 29b7a2d..19b280d 100644 --- a/src/test/java/edu/kit/scc/dem/wapsrv/testsrest/AnnotationRestTest.java +++ b/src/test/java/edu/kit/scc/dem/wapsrv/testsrest/AnnotationRestTest.java @@ -1127,6 +1127,58 @@ public void testPutAnnotationWithUnallowedChanges() { checkException(UnallowedPropertyChangeException.class, putResponse); } + /** + * Test put annotation with allowed changes. + * Via field and canonical field are not changeable but are allowed on PUT if they did not exist before + */ + @Test + public void testPutAnnotationWitAllowedChanges() { + String annotation = getAnnotation(0); // The one holds a canonical and a via value + assertNotNull(annotation, "Could not load example annotation"); + RequestSpecification request = RestAssured.given(); + request.contentType("application/ld+json;profile=\"http://www.w3.org/ns/anno.jsonld\""); + request.accept("application/ld+json;profile=\"http://www.w3.org/ns/anno.jsonld\""); + request.body(annotation); + Response response = postAnnotation(request); + assertNotNull(response, "Could not get response"); + assertEquals(AnnotationConstants.POST_ANNOTATION_SUCCESS_CODE, response.getStatusCode(), + "Annotation could not be created"); + final String annoInDb = response.getBody().asString(); + String etag = getEtag(response); + final String realId = getAnnotationId(response); + Response response2 = postAnnotation(request); + assertNotNull(response2, "Could not get response"); + assertEquals(AnnotationConstants.POST_ANNOTATION_SUCCESS_CODE, response2.getStatusCode(), + "Annotation could not be created"); + final String annoInDb2 = response2.getBody().asString(); + String etag2 = getEtag(response2); + final String realId2 = getAnnotationId(response2); + // post with a new via + String annoWithVia = annoInDb.replaceAll(Pattern.quote("\n}"), ",\n\"via\": \"http://newvia\"\n}"); + request = RestAssured.given(); + request.contentType("application/ld+json;profile=\"http://www.w3.org/ns/anno.jsonld\""); + request.accept("application/ld+json;profile=\"http://www.w3.org/ns/anno.jsonld\""); + request.header("If-Match", etag); + request.body(annoWithVia); + logger.trace("from : \n" + annoInDb + "\nto :\n" + annoWithVia); + Response putResponse = putAnnotation(request, realId); + assertNotNull(putResponse, "Could not get put response"); + assertEquals(AnnotationConstants.PUT_ANNOTATION_SUCCESS_CODE, putResponse.getStatusCode(), + "Annotation could not be updated."); + // post with a new canonical + String annoWithCanonical = annoInDb2.replaceAll(Pattern.quote("\n}"), ",\n\"canonical\": \"http://newcanon\"\n}"); + request = RestAssured.given(); + request.contentType("application/ld+json;profile=\"http://www.w3.org/ns/anno.jsonld\""); + request.accept("application/ld+json;profile=\"http://www.w3.org/ns/anno.jsonld\""); + request.header("If-Match", etag2); + request.body(annoWithCanonical); + logger.trace("from : \n" + annoInDb2 + "\nto :\n" + annoWithCanonical); + putResponse = putAnnotation(request, realId2); + assertNotNull(putResponse, "Could not get put response"); + assertEquals(AnnotationConstants.PUT_ANNOTATION_SUCCESS_CODE, putResponse.getStatusCode(), + "Annotation could not be updated."); + } + /** * Test posting annotation with a series of multiple escaped characters. * @throws JSONException