Skip to content

Commit

Permalink
Introducing RdfStreamProvider...
Browse files Browse the repository at this point in the history
  • Loading branch information
ajs6f committed Nov 19, 2013
1 parent 5c8fa63 commit 037d879
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 61 deletions.
Expand Up @@ -16,16 +16,13 @@

package org.fcrepo.http.api;

import static com.google.common.util.concurrent.Futures.addCallback;
import static javax.ws.rs.core.Response.noContent;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.status;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static org.fcrepo.http.commons.domain.RDFMediaType.N3;
import static org.fcrepo.http.commons.domain.RDFMediaType.N3_ALT1;
import static org.fcrepo.http.commons.domain.RDFMediaType.N3_ALT2;
import static org.fcrepo.http.commons.domain.RDFMediaType.NTRIPLES;
import static org.fcrepo.http.commons.domain.RDFMediaType.POSSIBLE_RDF_VARIANTS;
import static org.fcrepo.http.commons.domain.RDFMediaType.RDF_JSON;
import static org.fcrepo.http.commons.domain.RDFMediaType.RDF_XML;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE;
Expand All @@ -47,14 +44,12 @@
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Variant;

import org.fcrepo.http.commons.AbstractResource;
import org.fcrepo.http.commons.api.rdf.HttpGraphSubjects;
import org.fcrepo.http.commons.responses.RdfStreamStreamingOutput;
import org.fcrepo.http.commons.session.InjectedSession;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.utils.LogoutCallback;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.slf4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -85,30 +80,19 @@ public class FedoraVersions extends AbstractResource {
*/
@GET
@Produces({TURTLE, N3, N3_ALT1, N3_ALT2, RDF_XML, RDF_JSON, NTRIPLES})
public Response getVersionList(@PathParam("path")
public RdfStream getVersionList(@PathParam("path")
final List<PathSegment> pathList,
@Context
final Request request,
@Context
final UriInfo uriInfo) throws RepositoryException {
final String path = toPath(pathList);

LOGGER.trace("getting versions list for {}", path);

final Variant bestPossibleResponse =
request.selectVariant(POSSIBLE_RDF_VARIANTS);
LOGGER.trace("Getting versions list for: {}", path);

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

final RdfStreamStreamingOutput streamOutput =
new RdfStreamStreamingOutput(resource
.getVersionTriples(new HttpGraphSubjects(session,
FedoraVersions.class, uriInfo)),
bestPossibleResponse.getMediaType());

addCallback(streamOutput, new LogoutCallback(session));

return ok(streamOutput).build();
return resource.getVersionTriples(translator());
}

/**
Expand Down Expand Up @@ -150,7 +134,7 @@ public Response addVersionLabel(@PathParam("path")
@Path("/{versionLabel}")
@GET
@Produces({TURTLE, N3, N3_ALT1, N3_ALT2, RDF_XML, RDF_JSON, NTRIPLES})
public Response getVersion(@PathParam("path")
public RdfStream getVersion(@PathParam("path")
final List<PathSegment> pathList,
@PathParam("versionLabel")
final String versionLabel,
Expand All @@ -159,7 +143,7 @@ public Response getVersion(@PathParam("path")
@Context
final UriInfo uriInfo) throws RepositoryException, IOException {
final String path = toPath(pathList);
LOGGER.trace("getting version profile for {} at version {}", path,
LOGGER.trace("Getting version profile for: {} at version: {}", path,
versionLabel);

final FedoraResource resource =
Expand All @@ -168,19 +152,12 @@ public Response getVersion(@PathParam("path")
if (resource == null) {
throw new WebApplicationException(status(NOT_FOUND).build());
} else {

final Variant bestPossibleResponse =
request.selectVariant(POSSIBLE_RDF_VARIANTS);

final RdfStreamStreamingOutput streamOutput =
new RdfStreamStreamingOutput(resource
.getTriples(new HttpGraphSubjects(session,
FedoraVersions.class, uriInfo)),
bestPossibleResponse.getMediaType());

addCallback(streamOutput, new LogoutCallback(session));

return ok(streamOutput).build();
return resource.getTriples(translator());
}
}

protected GraphSubjects translator() {
return new HttpGraphSubjects(session, this.getClass(), uriInfo);
}

}
Expand Up @@ -87,16 +87,17 @@ public void testGetVersionList() throws RepositoryException {
mockVariant);
when(mockNodes.getObject(any(Session.class), anyString())).thenReturn(
mockResource);
final RdfStream testRdfStream = new RdfStream();
when(mockResource.getVersionTriples(any(HttpGraphSubjects.class)))
.thenReturn(new RdfStream());
.thenReturn(testRdfStream);
when(mockVariant.getMediaType()).thenReturn(
new MediaType("text", "turtle"));

final Response response =
final RdfStream response =
testObj.getVersionList(createPathList(pid), mockRequest,
getUriInfoImpl());
assertNotNull(response);
assertEquals(200, response.getStatus());
assertEquals("Got wrong RdfStream!", testRdfStream, response);
}

@Test
Expand Down
Expand Up @@ -255,9 +255,8 @@ private Template getTemplate(final Dataset rdf, final Node subject,
@Override
public boolean isWriteable(final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
return mediaType.equals(TEXT_HTML_TYPE) &&
(Dataset.class.isAssignableFrom(type) || Dataset.class
.isAssignableFrom(genericType.getClass()));
return mediaType.equals(TEXT_HTML_TYPE)
&& Dataset.class.isAssignableFrom(type) ;
}

@Override
Expand Down
Expand Up @@ -72,9 +72,7 @@ public boolean isWriteable(final Class<?> type, final Type genericType,
// we can return a result for any MIME type that Jena can serialize
final Boolean appropriateMimeType =
contentTypeToLang(mediaType.toString()) != null;
return appropriateMimeType &&
(Dataset.class.isAssignableFrom(type) || Dataset.class
.isAssignableFrom(genericType.getClass()));
return appropriateMimeType && Dataset.class.isAssignableFrom(type);
}

@Override
Expand Down
@@ -0,0 +1,72 @@
/**
* 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.commons.responses;

import static com.google.common.util.concurrent.Futures.addCallback;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;

import org.fcrepo.kernel.utils.LogoutCallback;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.springframework.stereotype.Component;


/**
* Provides serialization for streaming RDF results.
*
* @author ajs6f
* @date Nov 19, 2013
*/
@Provider
@Component
public class RdfStreamProvider implements MessageBodyWriter<RdfStream> {

@Override
public boolean isWriteable(final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
return RdfStream.class.isAssignableFrom(type) ;
}

@Override
public long getSize(final RdfStream t, final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
// We do not know how long the stream is
return -1;
}

@Override
public void writeTo(final RdfStream rdfStream, final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType,
final MultivaluedMap<String, Object> httpHeaders,
final OutputStream entityStream) throws IOException,
WebApplicationException {
final RdfStreamStreamingOutput streamOutput =
new RdfStreamStreamingOutput(rdfStream, mediaType);
addCallback(streamOutput, new LogoutCallback(rdfStream.session()));
streamOutput.write(entityStream);

}

}
Expand Up @@ -93,6 +93,6 @@ public NamespaceRdfContext(final Session session) throws RepositoryException {
createLiteral(nsURI)));
}
}
concat(nsTriples.build()).addNamespaces(namespaces.build());
concat(nsTriples.build()).namespaces(namespaces.build());
}
}
Expand Up @@ -311,7 +311,7 @@ public RdfStream getTreeTriples(final Node node) throws RepositoryException {
}

/**
* Decides whether the RDF represetnation of this {@link Node} will receive LDP Container status.
* Decides whether the RDF representation of this {@link Node} will receive LDP Container status.
*
* @param node
* @return
Expand Down
Expand Up @@ -23,6 +23,9 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.jcr.Session;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ForwardingIterator;
Expand All @@ -45,6 +48,8 @@ public class RdfStream extends ForwardingIterator<Triple> implements

protected Iterator<Triple> triples;

protected Session context;

private final static Triple[] NONE = new Triple[] {};

/**
Expand Down Expand Up @@ -120,7 +125,7 @@ public RdfStream() {
* @return
*/
public <Tr extends Triple, T extends Iterator<Tr>> RdfStream withThisContext(final T stream) {
return new RdfStream(stream).addNamespaces(namespaces());
return new RdfStream(stream).namespaces(namespaces());
}

/**
Expand All @@ -130,7 +135,7 @@ public <Tr extends Triple, T extends Iterator<Tr>> RdfStream withThisContext(fin
* @return
*/
public <Tr extends Triple, T extends Iterable<Tr>> RdfStream withThisContext(final T stream) {
return new RdfStream(stream).addNamespaces(namespaces());
return new RdfStream(stream).namespaces(namespaces());
}

/**
Expand Down Expand Up @@ -220,7 +225,7 @@ public <ToType> Iterator<ToType> transform(final Function<? super Triple, ToType
* @param uri
* @return This object for continued use.
*/
public RdfStream addNamespace(final String prefix, final String uri) {
public RdfStream namespace(final String prefix, final String uri) {
namespaces.put(prefix, uri);
return this;
}
Expand All @@ -229,11 +234,27 @@ public RdfStream addNamespace(final String prefix, final String uri) {
* @param nses
* @return This object for continued use.
*/
public RdfStream addNamespaces(final Map<String, String> nses) {
public RdfStream namespaces(final Map<String, String> nses) {
namespaces.putAll(nses);
return this;
}

/**
* @return The {@link Session} in context
*/
public Session session() {
return this.context;
}

/**
* Sets the JCR context of this stream
*
* @param session The {@link Session} in context
*/
public void session(final Session session) {
this.context = session;
}

/**
* WARNING!
*
Expand All @@ -258,7 +279,7 @@ public Model asModel() {
*/
public static RdfStream fromModel(final Model model) {
final Iterator<Triple> triples = Iterators.transform(model.listStatements(), statement2triple);
return new RdfStream(triples).addNamespaces(model.getNsPrefixMap());
return new RdfStream(triples).namespaces(model.getNsPrefixMap());
}

private static Function<Statement, Triple> statement2triple = new Function<Statement, Triple>() {
Expand Down
Expand Up @@ -204,7 +204,7 @@ public void setUp() throws RepositoryException {
when(mockTriples.hasNext()).thenReturn(true, true, false);
when(mockTriples.next()).thenReturn(descriptiveTriple, mixinTriple);
testStream = new RdfStream(mockTriples);
testStream.addNamespaces(mockNamespaceMap);
testStream.namespaces(mockNamespaceMap);
}


Expand Down
Expand Up @@ -159,7 +159,7 @@ public void setUp() throws RepositoryException {
when(mockTriples.hasNext()).thenReturn(true, true, false);
when(mockTriples.next()).thenReturn(descriptiveTriple, mixinTriple);
testStream = new RdfStream(mockTriples);
testStream.addNamespaces(mockNamespaceMap);
testStream.namespaces(mockNamespaceMap);
}


Expand Down

0 comments on commit 037d879

Please sign in to comment.