Skip to content

Commit

Permalink
LDP resource inlining
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeer committed Jul 25, 2013
1 parent 0a47a88 commit c7e62ad
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 39 deletions.
29 changes: 19 additions & 10 deletions fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraFieldSearch.java
Expand Up @@ -21,6 +21,7 @@
import static javax.ws.rs.core.MediaType.TEXT_HTML;
import static javax.ws.rs.core.Response.status;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static org.fcrepo.RdfLexicon.FIRST_PAGE;
import static org.fcrepo.RdfLexicon.NEXT_PAGE;
import static org.fcrepo.RdfLexicon.PAGE;
import static org.fcrepo.RdfLexicon.PAGE_OF;
Expand All @@ -38,8 +39,6 @@
import static org.fcrepo.http.RDFMediaType.TURTLE;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.Map;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.ws.rs.DefaultValue;
Expand All @@ -62,7 +61,6 @@
import org.springframework.stereotype.Component;

import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.ImmutableBiMap;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;
Expand Down Expand Up @@ -179,9 +177,10 @@ private Dataset getSearchDataset(final String terms, final long offset,
.build().toString());
}

final HttpGraphSubjects subjects = new HttpGraphSubjects(FedoraNodes.class, uriInfo);

final Dataset dataset =
nodeService.searchRepository(new HttpGraphSubjects(
FedoraNodes.class, uriInfo), searchResult,
nodeService.searchRepository(subjects, searchResult,
session, terms, limit, offset);

final Model searchModel = createDefaultModel();
Expand All @@ -205,20 +204,30 @@ private Dataset getSearchDataset(final String terms, final long offset,
SEARCH_HAS_MORE,
searchModel.createTypedLiteral(true))) {

final Map<String, ?> pathMap =
ImmutableBiMap.of("q", terms, "offset", offset + limit,
"limit", limit);

final Resource nextPageResource =
searchModel.createResource(uriInfo
.getBaseUriBuilder()
.path(FedoraFieldSearch.class)
.buildFromMap(pathMap)
.queryParam("q", terms)
.queryParam("offset", offset + limit)
.queryParam("limit", limit)
.toString());
searchModel.add(pageResource, NEXT_PAGE, nextPageResource);
} else {
searchModel.add(pageResource, NEXT_PAGE, RDF.nil);
}

final Resource firstPageResource =
searchModel.createResource(uriInfo
.getBaseUriBuilder()
.path(FedoraFieldSearch.class)
.queryParam("q", terms)
.queryParam("offset", 0)
.queryParam("limit", limit)
.toString());
searchModel.add(subjects.getContext(), FIRST_PAGE, firstPageResource);


dataset.addNamedModel("search-pagination", searchModel);
}

Expand Down
51 changes: 50 additions & 1 deletion fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraNodes.java
Expand Up @@ -25,6 +25,9 @@
import static org.apache.http.HttpStatus.SC_CONFLICT;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.apache.jena.riot.WebContent.contentTypeSPARQLUpdate;
import static org.fcrepo.RdfLexicon.FIRST_PAGE;
import static org.fcrepo.RdfLexicon.HAS_CHILD_COUNT;
import static org.fcrepo.RdfLexicon.NEXT_PAGE;
import static org.fcrepo.http.RDFMediaType.N3;
import static org.fcrepo.http.RDFMediaType.N3_ALT1;
import static org.fcrepo.http.RDFMediaType.N3_ALT2;
Expand Down Expand Up @@ -65,6 +68,8 @@
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriInfo;

import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import org.apache.commons.io.IOUtils;
import org.fcrepo.AbstractResource;
import org.fcrepo.FedoraResource;
Expand Down Expand Up @@ -118,6 +123,8 @@ public Dataset describe(@PathParam("path")
@QueryParam("limit")
@DefaultValue("-1")
final int limit,
@QueryParam("non-member-properties")
final String nonMemberProperties,
@Context
final Request request,
@Context
Expand Down Expand Up @@ -148,8 +155,50 @@ public Dataset describe(@PathParam("path")
}
final HttpGraphSubjects subjects =
new HttpGraphSubjects(FedoraNodes.class, uriInfo);

final int realLimit;
if (nonMemberProperties != null && limit == -1) {
realLimit = -2;
} else {
realLimit = limit;
}

final Dataset propertiesDataset =
resource.getPropertiesDataset(subjects, offset, limit);
resource.getPropertiesDataset(subjects, offset, realLimit);

if (limit > 0 && propertiesDataset.getDefaultModel()
.contains(subjects.getGraphSubject(resource.getNode()),
HAS_CHILD_COUNT)) {

Model requestModel = ModelFactory.createDefaultModel();

final long childCount = propertiesDataset.getDefaultModel()
.listObjectsOfProperty(subjects.getGraphSubject(resource.getNode()), HAS_CHILD_COUNT)
.nextNode().asLiteral().getLong();

if (childCount > (offset + limit)) {

final Resource nextPageResource =
requestModel.createResource(uriInfo
.getRequestUriBuilder()
.queryParam("offset", offset + limit)
.queryParam("limit", limit)
.toString());
requestModel.add(subjects.getContext(), NEXT_PAGE, nextPageResource);
}

final Resource firstPageResource =
requestModel.createResource(uriInfo
.getRequestUriBuilder()
.queryParam("offset", 0)
.queryParam("limit", limit)
.toString());
requestModel.add(subjects.getContext(), FIRST_PAGE, firstPageResource);

propertiesDataset.addNamedModel("requestModel", requestModel);

}

addResponseInformationToDataset(resource, propertiesDataset,
uriInfo, subjects);

Expand Down
Expand Up @@ -25,6 +25,7 @@
import static org.fcrepo.utils.FedoraJcrTypes.FEDORA_DATASTREAM;
import static org.fcrepo.utils.FedoraJcrTypes.FEDORA_OBJECT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
Expand Down Expand Up @@ -52,6 +53,8 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.hp.hpl.jena.graph.Node_ANY;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import org.apache.commons.io.IOUtils;
import org.fcrepo.FedoraObject;
import org.fcrepo.FedoraResource;
Expand Down Expand Up @@ -221,12 +224,33 @@ public void testDescribeObject() throws RepositoryException, IOException {
.thenReturn(mockObject);
final Request mockRequest = mock(Request.class);
final Dataset dataset =
testObj.describe(createPathList(path), 0, -1, mockRequest,
testObj.describe(createPathList(path), 0, -1, null, mockRequest,
uriInfo);
assertNotNull(dataset.getDefaultModel());

}

@Test
public void testDescribeObjectNoInlining() throws RepositoryException, IOException {
final String pid = "FedoraObjectsRdfTest1";
final String path = "/" + pid;

when(mockDataset.getDefaultModel()).thenReturn(mockModel);

when(mockObject.getLastModifiedDate()).thenReturn(null);
when(
mockObject.getPropertiesDataset(any(GraphSubjects.class),
anyLong(), eq(-2))).thenReturn(mockDataset);
when(mockNodes.getObject(isA(Session.class), isA(String.class)))
.thenReturn(mockObject);
final Request mockRequest = mock(Request.class);
final Dataset dataset =
testObj.describe(createPathList(path), 0, -1, "", mockRequest,
uriInfo);
assertNotNull(dataset.getDefaultModel());

}

@Test
public void testSparqlUpdate() throws RepositoryException, IOException {
final String pid = "FedoraObjectsRdfTest1";
Expand Down
Expand Up @@ -195,6 +195,15 @@ public void testGetObjectGraph() throws Exception {

logger.debug("Retrieved object graph:\n" + content);


assertTrue(
"Expect inlined resources",
compile(
"<" +
serverAddress +
"objects/FedoraDescribeTestGraph> <http://www.w3.org/ns/ldp#inlinedResource>",
DOTALL).matcher(content).find());

assertTrue(
"Didn't find an expected ntriple",
compile(
Expand All @@ -213,6 +222,29 @@ public void testGetObjectGraph() throws Exception {

}

@Test
public void testGetObjectGraphNonMemberProperties() throws Exception {
client.execute(postObjMethod("FedoraDescribeTestGraph"));
final HttpGet getObjMethod =
new HttpGet(serverAddress + "objects/FedoraDescribeTestGraph?non-member-properties");
getObjMethod.addHeader("Accept", "application/n-triples");
final HttpResponse response = client.execute(getObjMethod);
assertEquals(OK.getStatusCode(), response.getStatusLine()
.getStatusCode());
final String content = EntityUtils.toString(response.getEntity());

logger.debug("Retrieved object graph:\n" + content);

assertFalse(
"Didn't expect inlined resources",
compile(
"<" +
serverAddress +
"objects/FedoraDescribeTestGraph> <http://www.w3.org/ns/ldp#inlinedResource>",
DOTALL).matcher(content).find());

}

@Test
public void testGetObjectGraphByUUID() throws Exception {
client.execute(postObjMethod("FedoraDescribeTestGraphByUuid"));
Expand Down
Expand Up @@ -52,6 +52,7 @@ public class HttpGraphSubjects implements GraphSubjects {
private final String basePath;

private final int pathIx;
private final URI context;

/**
* Build HTTP graph subjects relative to the given JAX-RS resource, using the UriInfo provided.
Expand All @@ -63,6 +64,7 @@ public class HttpGraphSubjects implements GraphSubjects {
* @param uris
*/
public HttpGraphSubjects(final Class<?> relativeTo, final UriInfo uris) {
this.context = uris.getRequestUri();
this.nodesBuilder = uris.getBaseUriBuilder().path(relativeTo);
String basePath = nodesBuilder.build("").toString();
if (!basePath.endsWith("/")) {
Expand All @@ -83,6 +85,11 @@ public Resource getGraphSubject(final Session session, final String absPath)
return ResourceFactory.createResource(result.toString());
}

@Override
public Resource getContext() {
return ResourceFactory.createResource(context.toString());
}

@Override
public Resource getGraphSubject(final Node node) throws RepositoryException {
final URI result = nodesBuilder.buildFromMap(getPathMap(node));
Expand Down
Expand Up @@ -60,6 +60,7 @@ public void writeTo(final Dataset rdf, final Class<?> type,

// add standard headers
httpHeaders.put("Content-type", of((Object) mediaType.toString()));
httpHeaders.putSingle("Link", ";rel=\"first\"");
setCachingHeaders(httpHeaders, rdf);

new GraphStoreStreamingOutput(rdf, mediaType).write(entityStream);
Expand Down
Expand Up @@ -58,12 +58,14 @@ public class HttpGraphSubjectsTest {
@Mock
private Node mockNode;

private UriInfo uriInfo;

@Before
public void setUp() {
initMocks(this);
final UriInfo uris = getUriInfoImpl(testPath);
uriInfo = getUriInfoImpl(testPath);
testObj =
new HttpGraphSubjects(MockNodeController.class, uris);
new HttpGraphSubjects(MockNodeController.class, uriInfo);
}

@Test
Expand Down Expand Up @@ -126,6 +128,11 @@ public void testIsFedoraGraphSubject() {
assertEquals(false, actual);
}

@Test
public void testGetContext() {
assertEquals(uriInfo.getRequestUri().toString(), testObj.getContext().getURI());
}

private static UriInfo getUriInfoImpl(final String path) {
// UriInfo ui = mock(UriInfo.class,withSettings().verboseLogging());
final UriInfo ui = mock(UriInfo.class);
Expand Down
3 changes: 3 additions & 0 deletions fcrepo-kernel/src/main/java/org/fcrepo/RdfLexicon.java
Expand Up @@ -74,6 +74,9 @@ public final class RdfLexicon {
createProperty("http://www.w3.org/ns/ldp#Page");
public static final Property PAGE_OF =
createProperty("http://www.w3.org/ns/ldp#pageOf");

public static final Property FIRST_PAGE =
createProperty("http://www.w3.org/ns/ldp#firstPage");
public static final Property NEXT_PAGE =
createProperty("http://www.w3.org/ns/ldp#nextPage");

Expand Down
6 changes: 6 additions & 0 deletions fcrepo-kernel/src/main/java/org/fcrepo/rdf/GraphSubjects.java
Expand Up @@ -61,4 +61,10 @@ Node getNodeFromGraphSubject(final Session session, final Resource subject)
* @throws RepositoryException
*/
Resource getGraphSubject(final Session session, final String absPath) throws RepositoryException;

/**
* Get a context resource
* @return
*/
Resource getContext();
}
Expand Up @@ -37,6 +37,14 @@
*/
public class DefaultGraphSubjects implements GraphSubjects {

private final Resource context;

/**
* Construct the graph with a placeholder context resource
*/
public DefaultGraphSubjects() {
this.context = ResourceFactory.createResource();
}

@Override
public Resource getGraphSubject(final Session session, final String absPath) throws RepositoryException {
Expand All @@ -50,6 +58,11 @@ public Resource getGraphSubject(final Session session, final String absPath) thr
}
}

@Override
public Resource getContext() {
return context;
}

@Override
public Resource getGraphSubject(final Node node) throws RepositoryException {
return getGraphSubject(node.getSession(), node.getPath());
Expand Down

0 comments on commit c7e62ad

Please sign in to comment.