Skip to content

Commit

Permalink
Changed FedoraNodes.describe() to stream, everything works except HTM…
Browse files Browse the repository at this point in the history
…L ITs
  • Loading branch information
ajs6f committed Nov 20, 2013
1 parent 760b842 commit 36c6051
Show file tree
Hide file tree
Showing 41 changed files with 506 additions and 192 deletions.
154 changes: 66 additions & 88 deletions fcrepo-http-api/src/main/java/org/fcrepo/http/api/FedoraNodes.java
Expand Up @@ -16,6 +16,8 @@

package org.fcrepo.http.api;

import static com.hp.hpl.jena.graph.NodeFactory.createURI;
import static com.hp.hpl.jena.graph.Triple.create;
import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
import static com.sun.jersey.api.Responses.clientError;
import static com.sun.jersey.api.Responses.notAcceptable;
Expand All @@ -42,9 +44,7 @@
import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_DATASTREAM;
import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_OBJECT;
import static org.fcrepo.kernel.RdfLexicon.FIRST_PAGE;
import static org.fcrepo.kernel.RdfLexicon.HAS_CHILD_COUNT;
import static org.fcrepo.kernel.RdfLexicon.NEXT_PAGE;
import static org.fcrepo.kernel.rdf.GraphProperties.INLINED_RESOURCES_MODEL;
import static org.fcrepo.kernel.rdf.GraphProperties.PROBLEMS_MODEL_NAME;
import static org.slf4j.LoggerFactory.getLogger;

Expand Down Expand Up @@ -95,15 +95,16 @@
import org.fcrepo.kernel.Datastream;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.modeshape.jcr.api.JcrConstants;
import org.slf4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.codahale.metrics.annotation.Timed;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;

/**
* CRUD operations on Fedora Nodes
Expand Down Expand Up @@ -135,108 +136,85 @@ public class FedoraNodes extends AbstractResource {
@GET
@Produces({TURTLE, N3, N3_ALT1, N3_ALT2, RDF_XML, RDF_JSON, NTRIPLES,
TEXT_HTML})
public Dataset describe(@PathParam("path") final List<PathSegment> pathList,
public RdfStream describe(@PathParam("path") final List<PathSegment> pathList,
@QueryParam("offset") @DefaultValue("0") final int offset,
@QueryParam("limit") @DefaultValue("-1") final int limit,
@QueryParam("non-member-properties") final String nonMemberProperties,
@Context final Request request,
@Context final HttpServletResponse servletResponse,
@Context final UriInfo uriInfo) throws RepositoryException, IOException {
final String path = toPath(pathList);
logger.trace("Getting profile for {}", path);
logger.trace("Getting profile for: {}", path);

try {
final FedoraResource resource =
nodeService.getObject(session, path);


final EntityTag etag = new EntityTag(resource.getEtagValue());
final Date date = resource.getLastModifiedDate();
final Date roundedDate = new Date();
if (date != null) {
roundedDate.setTime(date.getTime() - date.getTime() % 1000);
}
final ResponseBuilder builder =
request.evaluatePreconditions(roundedDate, etag);
if (builder != null) {
final CacheControl cc = new CacheControl();
cc.setMaxAge(0);
cc.setMustRevalidate(true);
// here we are implicitly emitting a 304
// the exception is not an error, it's genuinely
// an exceptional condition
throw new WebApplicationException(builder.cacheControl(cc)
.lastModified(date).tag(etag).build());
}
final HttpGraphSubjects subjects =
new HttpGraphSubjects(session, FedoraNodes.class, uriInfo);

final int realLimit;
if (nonMemberProperties != null && limit == -1) {
realLimit = -2;
} else {
realLimit = limit;
}
final FedoraResource resource = nodeService.getObject(session, path);

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

final Model treeModel = propertiesDataset.getNamedModel(
propertiesDataset.getContext()
.getAsString(INLINED_RESOURCES_MODEL,
"NO SUCH MODEL"));
if (limit > 0 && treeModel != null && treeModel
.contains(subjects.getGraphSubject(resource.getNode()),
HAS_CHILD_COUNT)) {

final Model requestModel = createDefaultModel();

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

if (childCount > (offset + limit)) {

final Resource nextPageResource =
requestModel.createResource(uriInfo
.getRequestUriBuilder()
.replaceQueryParam("offset", offset + limit)
.replaceQueryParam("limit", limit)
.build()
.toString());
requestModel.add(subjects.getContext(), NEXT_PAGE, nextPageResource);
}
final EntityTag etag = new EntityTag(resource.getEtagValue());
final Date date = resource.getLastModifiedDate();
final Date roundedDate = new Date();
if (date != null) {
roundedDate.setTime(date.getTime() - date.getTime() % 1000);
}
final ResponseBuilder builder =
request.evaluatePreconditions(roundedDate, etag);
if (builder != null) {
final CacheControl cc = new CacheControl();
cc.setMaxAge(0);
cc.setMustRevalidate(true);
// here we are implicitly emitting a 304
// the exception is not an error, it's genuinely
// an exceptional condition
throw new WebApplicationException(builder.cacheControl(cc)
.lastModified(date).tag(etag).build());
}
final HttpGraphSubjects subjects =
new HttpGraphSubjects(session, this.getClass(), uriInfo);

final String firstPage = uriInfo
.getRequestUriBuilder()
.replaceQueryParam("offset", 0)
.replaceQueryParam("limit", limit)
.build().toString();
final Resource firstPageResource =
requestModel.createResource(firstPage);
servletResponse.addHeader("Link", firstPage + ";rel=\"first\"");
requestModel.add(subjects.getContext(), FIRST_PAGE, firstPageResource);
final int realLimit;
if (nonMemberProperties != null && limit == -1) {
realLimit = -2;
} else {
realLimit = limit;
}

propertiesDataset.addNamedModel("requestModel", requestModel);
final RdfStream rdfStream =
resource.getTriples(subjects).concat(
resource.getHierarchyTriples(subjects)).session(session);
if (realLimit != -2) {
final Node firstPage =
createURI(uriInfo.getRequestUriBuilder().replaceQueryParam(
"offset", 0).replaceQueryParam("limit", limit).build()
.toString().replace("&", "&amp;"));
final Node nextPage =
createURI(uriInfo.getRequestUriBuilder().replaceQueryParam(
"offset", offset + limit).replaceQueryParam("limit",
limit).build().toString().replace("&", "&amp;"));
rdfStream.concat(
create(subjects.getContext().asNode(), NEXT_PAGE.asNode(),
nextPage),
create(subjects.getContext().asNode(), FIRST_PAGE.asNode(),
firstPage)).limit(realLimit).skip(offset);

servletResponse.addHeader("Link", firstPage + ";rel=\"first\"");
}

}

if (!etag.getValue().isEmpty()) {
servletResponse.addHeader("ETag", etag.toString());
}
if (!etag.getValue().isEmpty()) {
servletResponse.addHeader("ETag", etag.toString());
}

servletResponse.addHeader("Accept-Patch", contentTypeSPARQLUpdate);
servletResponse.addHeader("Link", "http://www.w3.org/ns/ldp/Resource;rel=\"type\"");
if (resource.getLastModifiedDate() != null) {
servletResponse.addDateHeader("Last-Modified", resource
.getLastModifiedDate().getTime());
}
servletResponse.addHeader("Accept-Patch", contentTypeSPARQLUpdate);
servletResponse.addHeader("Link",
"http://www.w3.org/ns/ldp/Resource;rel=\"type\"");

addResponseInformationToDataset(resource, propertiesDataset,
uriInfo, subjects);
addResponseInformationToStream(resource, rdfStream, uriInfo,
subjects);

return propertiesDataset;
return rdfStream;

} finally {
session.logout();
}

}

Expand Down
Expand Up @@ -92,7 +92,7 @@ public RdfStream getVersionList(@PathParam("path")

final FedoraResource resource = nodeService.getObject(session, path);

return resource.getVersionTriples(translator());
return resource.getVersionTriples(translator()).session(session);
}

/**
Expand Down Expand Up @@ -152,7 +152,7 @@ public RdfStream getVersion(@PathParam("path")
if (resource == null) {
throw new WebApplicationException(status(NOT_FOUND).build());
} else {
return resource.getTriples(translator());
return resource.getTriples(translator()).session(session);
}
}

Expand Down
Expand Up @@ -57,7 +57,7 @@
import org.fcrepo.http.commons.responses.HtmlTemplate;
import org.fcrepo.http.commons.session.InjectedSession;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.utils.JcrRdfTools;
import org.fcrepo.kernel.rdf.JcrRdfTools;
import org.slf4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
Expand Down
@@ -0,0 +1,28 @@
/**
* Copyright 2013 DuraSpace, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fcrepo.http.api.responses;

import org.fcrepo.http.commons.responses.StreamingBaseHtmlProvider;
import org.springframework.stereotype.Component;

/**
* JAX-RS provider for taking an {@link RdfStream} and returning some nice looking
* HTML
*/
@Component
public class StreamingHtmlProvider extends StreamingBaseHtmlProvider{

}
Expand Up @@ -33,7 +33,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
Expand All @@ -49,6 +48,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Calendar;
import java.util.Date;

import javax.jcr.ItemExistsException;
import javax.jcr.Node;
Expand All @@ -73,6 +73,7 @@
import org.fcrepo.kernel.services.NodeService;
import org.fcrepo.kernel.services.ObjectService;
import org.fcrepo.kernel.services.VersionService;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
Expand Down Expand Up @@ -116,6 +117,10 @@ public class FedoraNodesTest {
@Mock
private Dataset mockDataset;

private RdfStream mockRdfStream = new RdfStream();

private RdfStream mockRdfStream2 = new RdfStream();

@Mock
private Model mockModel;

Expand All @@ -128,7 +133,10 @@ public class FedoraNodesTest {
@Mock
private PidMinter mockPidMinter;

private UriInfo uriInfo;
@Mock
private Date mockDate;

private UriInfo mockUriInfo;

@Before
public void setUp() throws Exception {
Expand All @@ -137,8 +145,7 @@ public void setUp() throws Exception {
setField(testObj, "datastreamService", mockDatastreams);
setField(testObj, "nodeService", mockNodes);
setField(testObj, "versionService", mockVersions);
this.uriInfo = getUriInfoImpl();
setField(testObj, "uriInfo", uriInfo);
this.mockUriInfo = getUriInfoImpl();
setField(testObj, "pidMinter", mockPidMinter);
setField(testObj, "objectService", mockObjects);
mockSession = mockSession(testObj);
Expand All @@ -148,6 +155,7 @@ public void setUp() throws Exception {
when(mockSession.getWorkspace()).thenReturn(mockWorkspace);
final VersionManager mockVM = mock(VersionManager.class);
when(mockWorkspace.getVersionManager()).thenReturn(mockVM);
when(mockDate.getTime()).thenReturn(0L);
}

@Test
Expand Down Expand Up @@ -270,18 +278,20 @@ public void testDescribeObject() throws RepositoryException, IOException {

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

when(mockObject.getLastModifiedDate()).thenReturn(mockDate);
when(mockObject.getEtagValue()).thenReturn("");
when(
mockObject.getPropertiesDataset(any(GraphSubjects.class),
anyInt(), anyInt())).thenReturn(mockDataset);
when(mockObject.getTriples(any(GraphSubjects.class))).thenReturn(
mockRdfStream);
when(mockObject.getHierarchyTriples(any(GraphSubjects.class))).thenReturn(
mockRdfStream2);
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, null, mockRequest, mockResponse,
uriInfo);
assertNotNull(dataset.getDefaultModel());
final RdfStream rdfStream =
testObj.describe(createPathList(path), 0, -2, null, mockRequest,
mockResponse, mockUriInfo);
assertEquals("Got wrong triples!", mockRdfStream.concat(mockRdfStream2),
rdfStream);
verify(mockResponse).addHeader("Accept-Patch", "application/sparql-update");

}
Expand All @@ -295,16 +305,19 @@ public void testDescribeObjectNoInlining() throws RepositoryException, IOExcepti
when(mockDataset.getContext()).thenReturn(mockContext);

when(mockObject.getEtagValue()).thenReturn("");
when(
mockObject.getPropertiesDataset(any(GraphSubjects.class),
anyInt(), eq(-2))).thenReturn(mockDataset);
when(mockObject.getLastModifiedDate()).thenReturn(mockDate);
when(mockObject.getTriples(any(GraphSubjects.class))).thenReturn(
mockRdfStream);
when(mockObject.getHierarchyTriples(any(GraphSubjects.class))).thenReturn(
mockRdfStream2);
when(mockNodes.getObject(isA(Session.class), isA(String.class)))
.thenReturn(mockObject);
final Request mockRequest = mock(Request.class);
final Dataset dataset =
final RdfStream rdfStream =
testObj.describe(createPathList(path), 0, -1, "", mockRequest, mockResponse,
uriInfo);
assertNotNull(dataset.getDefaultModel());
mockUriInfo);
assertEquals("Got wrong RDF!", mockRdfStream.concat(mockRdfStream2),
rdfStream);

}

Expand Down

0 comments on commit 36c6051

Please sign in to comment.