From 19bd279c828172954b770fcdff841192f5955f57 Mon Sep 17 00:00:00 2001 From: Aaron Coburn Date: Thu, 4 Apr 2019 15:03:38 -0400 Subject: [PATCH] Adjust PATCH requests to operate on externalized IRIs Resolves #386 This also adds an integration test to check this behavior --- .../java/org/trellisldp/test/LdpRdfTests.java | 23 ++++++++++++++++++- .../trellisldp/http/impl/PatchHandler.java | 8 ++++--- .../trellisldp/http/impl/BaseTestHandler.java | 2 ++ .../http/impl/PatchHandlerTest.java | 5 ++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/components/test/src/main/java/org/trellisldp/test/LdpRdfTests.java b/components/test/src/main/java/org/trellisldp/test/LdpRdfTests.java index c3600559d..439770741 100644 --- a/components/test/src/main/java/org/trellisldp/test/LdpRdfTests.java +++ b/components/test/src/main/java/org/trellisldp/test/LdpRdfTests.java @@ -265,7 +265,8 @@ default void testPatchRDF() { assertAll("Check an LDP-RS resource", checkRdfResponse(res, LDP.RDFSource, null)); } - await().until(() -> !initialETag.equals(getETag(getResourceLocation()))); + final EntityTag etag2 = getETag(getResourceLocation()); + await().until(() -> !initialETag.equals(etag2)); // Fetch the updated resource try (final Response res = target(getResourceLocation()).request().accept("application/n-triples").get()) { @@ -277,6 +278,26 @@ default void testPatchRDF() { assertTrue(res.getEntityTag().isWeak(), "Check that the ETag is weak"); assertNotEquals(initialETag, res.getEntityTag(), "Compare the first and second ETags"); } + + // Now remove the triple + try (final Response res = target(getResourceLocation()).request().method("PATCH", + entity("DELETE DATA { <" + getResourceLocation() + "> " + + "\"Title\" }", APPLICATION_SPARQL_UPDATE))) { + assertAll("Check an LDP-RS resource", checkRdfResponse(res, LDP.RDFSource, null)); + } + + await().until(() -> !etag2.equals(getETag(getResourceLocation()))); + + // Fetch the updated resource + try (final Response res = target(getResourceLocation()).request().accept("application/n-triples").get()) { + assertAll("Check an updated resource", checkRdfResponse(res, LDP.RDFSource, APPLICATION_N_TRIPLES_TYPE)); + final Graph g = readEntityAsGraph(res.getEntity(), getBaseURL(), NTRIPLES); + assertEquals(3L, g.size(), "Check the graph size"); + assertFalse(g.contains(rdf.createIRI(getResourceLocation()), DC.title, rdf.createLiteral("Title")), + "Check for a dc:title triple"); + assertTrue(res.getEntityTag().isWeak(), "Check that the ETag is weak"); + assertNotEquals(etag2, res.getEntityTag(), "Compare the second and third ETags"); + } } /** diff --git a/core/http/src/main/java/org/trellisldp/http/impl/PatchHandler.java b/core/http/src/main/java/org/trellisldp/http/impl/PatchHandler.java index df9c9313a..66314dd1b 100644 --- a/core/http/src/main/java/org/trellisldp/http/impl/PatchHandler.java +++ b/core/http/src/main/java/org/trellisldp/http/impl/PatchHandler.java @@ -29,7 +29,6 @@ import static org.slf4j.LoggerFactory.getLogger; import static org.trellisldp.api.Resource.SpecialResources.DELETED_RESOURCE; import static org.trellisldp.api.Resource.SpecialResources.MISSING_RESOURCE; -import static org.trellisldp.api.TrellisUtils.TRELLIS_DATA_PREFIX; import static org.trellisldp.http.core.HttpConstants.ACL; import static org.trellisldp.http.core.HttpConstants.PREFERENCE_APPLIED; import static org.trellisldp.http.core.Prefer.PREFER_REPRESENTATION; @@ -185,10 +184,13 @@ private List updateGraph(final RDFSyntax syntax, final IRI graphName) { // Update existing graph try (final TrellisGraph graph = TrellisGraph.createGraph()) { try (final Stream stream = getResource().stream(graphName)) { - stream.map(Quad::asTriple).forEachOrdered(graph::add); + stream.map(Quad::asTriple) + .map(unskolemizeTriples(getServices().getResourceService(), getBaseUrl())) + .forEachOrdered(graph::add); } + getServices().getIOService().update(graph.asGraph(), updateBody, syntax, - TRELLIS_DATA_PREFIX + getRequest().getPath() + (ACL.equals(getRequest().getExt()) ? "?ext=acl" : "")); + getBaseUrl() + getRequest().getPath() + (ACL.equals(getRequest().getExt()) ? "?ext=acl" : "")); triples = graph.stream().filter(triple -> !RDF.type.equals(triple.getPredicate()) || !triple.getObject().ntriplesString().startsWith("<" + LDP.getNamespace())).collect(toList()); } diff --git a/core/http/src/test/java/org/trellisldp/http/impl/BaseTestHandler.java b/core/http/src/test/java/org/trellisldp/http/impl/BaseTestHandler.java index b202bfc4d..18c8bba00 100644 --- a/core/http/src/test/java/org/trellisldp/http/impl/BaseTestHandler.java +++ b/core/http/src/test/java/org/trellisldp/http/impl/BaseTestHandler.java @@ -215,6 +215,8 @@ private void setUpResourceService() { when(mockResourceService.replace(any(Metadata.class), any(Dataset.class))).thenReturn(completedFuture(null)); when(mockResourceService.delete(any(Metadata.class))).thenReturn(completedFuture(null)); when(mockResourceService.add(any(IRI.class), any(Dataset.class))).thenReturn(completedFuture(null)); + when(mockResourceService.unskolemize(any(Literal.class))).then(returnsFirstArg()); + when(mockResourceService.unskolemize(any(IRI.class))).thenCallRealMethod(); when(mockResourceService.skolemize(any(Literal.class))).then(returnsFirstArg()); when(mockResourceService.skolemize(any(IRI.class))).then(returnsFirstArg()); when(mockResourceService.skolemize(any(BlankNode.class))).thenAnswer(inv -> diff --git a/core/http/src/test/java/org/trellisldp/http/impl/PatchHandlerTest.java b/core/http/src/test/java/org/trellisldp/http/impl/PatchHandlerTest.java index 4f36e4f4e..30e3d9ec5 100644 --- a/core/http/src/test/java/org/trellisldp/http/impl/PatchHandlerTest.java +++ b/core/http/src/test/java/org/trellisldp/http/impl/PatchHandlerTest.java @@ -103,6 +103,7 @@ public void testEntity() { when(mockTrellisRequest.getContentType()).thenReturn(APPLICATION_SPARQL_UPDATE); when(mockResource.stream(eq(PreferUserManaged))).thenAnswer(x -> of(quad)); when(mockTrellisRequest.getPath()).thenReturn("resource"); + when(mockTrellisRequest.getBaseUrl()).thenReturn("http://localhost/"); final PatchHandler patchHandler = new PatchHandler(mockTrellisRequest, insert, mockBundler, null, null); final Response res = patchHandler.updateResource(patchHandler.initialize(mockParent, mockResource)) @@ -110,7 +111,7 @@ public void testEntity() { assertEquals(NO_CONTENT, res.getStatusInfo(), "Incorrect response code!"); - verify(mockIoService).update(any(Graph.class), eq(insert), eq(SPARQL_UPDATE), eq(identifier.getIRIString())); + verify(mockIoService).update(any(Graph.class), eq(insert), eq(SPARQL_UPDATE), eq("http://localhost/resource")); verify(mockResourceService).replace(any(Metadata.class), any(Dataset.class)); } @@ -188,7 +189,7 @@ public void testError2() { when(mockTrellisRequest.getContentType()).thenReturn(APPLICATION_SPARQL_UPDATE); when(mockTrellisRequest.getPath()).thenReturn("resource"); doThrow(RuntimeTrellisException.class).when(mockIoService) - .update(any(Graph.class), eq(insert), eq(SPARQL_UPDATE), eq(identifier.getIRIString())); + .update(any(Graph.class), eq(insert), eq(SPARQL_UPDATE), eq(baseUrl + "resource")); final PatchHandler patchHandler = new PatchHandler(mockTrellisRequest, insert, mockBundler, null, baseUrl); final Response res = assertThrows(BadRequestException.class, () ->