Skip to content

Commit

Permalink
Fedora transformation service
Browse files Browse the repository at this point in the history
Transform a Node's property graph to some other format. Out of the box,
we have an LDPath implementation (and a JSON output that is solr
friendly) and SPARQL-Query
  • Loading branch information
cbeer committed Jul 18, 2013
1 parent d586940 commit 0ad4c4b
Show file tree
Hide file tree
Showing 30 changed files with 2,112 additions and 1 deletion.
@@ -0,0 +1,90 @@
/**
* 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.responses;

import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.sparql.resultset.ResultsFormat;
import org.slf4j.Logger;
import org.springframework.stereotype.Component;

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 java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import static com.google.common.collect.ImmutableList.of;
import static org.slf4j.LoggerFactory.getLogger;

/**
* Helper for writing QueryExecutions results out in a variety
* of serialization formats.
*
*/
@Provider
@Component
public class QueryExecutionProvider implements MessageBodyWriter<QueryExecution> {

private static final Logger logger = getLogger(QueryExecutionProvider.class);

@Override
public void writeTo(final QueryExecution qexec, final Class<?> type,
final Type genericType, final Annotation[] annotations,
final MediaType mediaType,
final MultivaluedMap<String, Object> httpHeaders,
final OutputStream entityStream) throws IOException,
WebApplicationException {

logger.debug("Writing a response for: {} with MIMEtype: {}", qexec,
mediaType);

// add standard headers
httpHeaders.put("Content-type", of((Object) mediaType.toString()));

try {
final ResultSet results = qexec.execSelect();
new ResultSetStreamingOutput(results, mediaType).write(entityStream);
} finally {
qexec.close();
}
}

@Override
public boolean isWriteable(final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {

// we can return a result for any MIME type that Jena can serialize
final Boolean appropriateResultType = ResultSetStreamingOutput.getResultsFormat(mediaType) != ResultsFormat.FMT_UNKNOWN;
return appropriateResultType &&
(QueryExecution.class.isAssignableFrom(type) || QueryExecution.class
.isAssignableFrom(genericType.getClass()));
}

@Override
public long getSize(final QueryExecution rdf, final Class<?> type,
final Type genericType, final Annotation[] annotations,
final MediaType mediaType) {
// we don't know in advance how large the result might be
return -1;
}

}
@@ -0,0 +1,111 @@
/**
* 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.responses;

import com.hp.hpl.jena.query.DatasetFactory;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.sparql.resultset.ResultsFormat;
import org.apache.jena.riot.WebContent;

import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.io.OutputStream;

/**
* Stream the results of a SPARQL Query
*/
class ResultSetStreamingOutput {
private final ResultSet results;
private final MediaType mediaType;

/**
* Stream the results of a SPARQL Query with the given MediaType
* @param results
* @param mediaType
*/
public ResultSetStreamingOutput(final ResultSet results, final MediaType mediaType) {
this.mediaType = mediaType;
this.results = results;
}

/**
*
* @param entityStream
* @throws IOException
*/
public void write(OutputStream entityStream) throws IOException {

final ResultsFormat resultsFormat = getResultsFormat(mediaType);

if (resultsFormat == ResultsFormat.FMT_UNKNOWN) {
new GraphStoreStreamingOutput(DatasetFactory.create(ResultSetFormatter.toModel(results)), mediaType).write(entityStream);
} else {
ResultSetFormatter.output(entityStream, results, resultsFormat);
}

}

/**
* Map the HTTP MediaType to a SPARQL ResultsFormat
* @param mediaType
* @return
*/
public static ResultsFormat getResultsFormat(final MediaType mediaType) {
switch (mediaType.toString()) {
case WebContent.contentTypeTextTSV:
return ResultsFormat.FMT_RS_TSV;

case WebContent.contentTypeTextCSV:
return ResultsFormat.FMT_RS_CSV;

case WebContent.contentTypeSSE:
return ResultsFormat.FMT_RS_SSE;

case WebContent.contentTypeTextPlain:
return ResultsFormat.FMT_TEXT;

case WebContent.contentTypeResultsJSON:
return ResultsFormat.FMT_RS_JSON;

case WebContent.contentTypeResultsXML:
return ResultsFormat.FMT_RS_XML;

case WebContent.contentTypeResultsBIO:
return ResultsFormat.FMT_RS_BIO;

case WebContent.contentTypeTurtle:
case WebContent.contentTypeTurtleAlt1:
case WebContent.contentTypeTurtleAlt2:
return ResultsFormat.FMT_RDF_TTL;

case WebContent.contentTypeN3:
case WebContent.contentTypeN3Alt1:
case WebContent.contentTypeN3Alt2:
return ResultsFormat.FMT_RDF_N3;

case WebContent.contentTypeNTriples:
return ResultsFormat.FMT_RDF_NT;

case WebContent.contentTypeRDFXML:
return ResultsFormat.FMT_RDF_XML;

}

return ResultsFormat.FMT_UNKNOWN;
}
}
@@ -0,0 +1,109 @@
/**
* 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.responses;

import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.sparql.core.DatasetImpl;
import org.apache.commons.io.IOUtils;
import org.apache.jena.riot.WebContent;
import org.junit.Test;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Type;

import static com.hp.hpl.jena.graph.NodeFactory.createLiteral;
import static com.hp.hpl.jena.graph.NodeFactory.createURI;
import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
import static javax.ws.rs.core.MediaType.TEXT_HTML_TYPE;
import static javax.ws.rs.core.MediaType.valueOf;
import static org.fcrepo.responses.RdfSerializationUtils.primaryTypePredicate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

public class QueryExecutionProviderTest {

final QueryExecutionProvider testObj = new QueryExecutionProvider();

Dataset testData = new DatasetImpl(createDefaultModel());


{
testData.asDatasetGraph().getDefaultGraph().add(
new Triple(createURI("test:subject"),
createURI("test:predicate"),
createLiteral("test:object")));
testData.asDatasetGraph().getDefaultGraph().add(
new Triple(createURI("test:subject"), primaryTypePredicate,
createLiteral("nt:file")));

}

@SuppressWarnings("unchecked")
@Test
public void testWriteTo() throws WebApplicationException,
IllegalArgumentException, IOException {

final Query sparqlQuery =
QueryFactory.create("SELECT ?x WHERE { ?x ?y ?z }");

QueryExecution testResult = QueryExecutionFactory.create(sparqlQuery, testData);

final ByteArrayOutputStream outStream = new ByteArrayOutputStream();

testObj.writeTo(testResult, QueryExecution.class, mock(Type.class), null,
valueOf(WebContent.contentTypeResultsXML), mock(MultivaluedMap.class),
outStream);
final byte[] results = outStream.toByteArray();
assertTrue("Got no output from serialization!", results.length > 0);
assertTrue("Couldn't find test RDF-object mentioned!", new String(
results).contains("test:subject"));
}

@Test
public void testGetSize() {
assertEquals("Returned wrong size from QueryExecutionProvider!", testObj
.getSize(null, null, null, null, null), -1);

}

@Test
public void testIsWritable() throws Exception {
assertTrue(
"Gave false response to QueryExecutionProvider.isWriteable() that contained a legitimate combination of parameters!",
testObj.isWriteable(QueryExecution.class, QueryExecution.class, null,
valueOf(WebContent.contentTypeResultsXML)));
assertFalse(
"RdfProvider.isWriteable() should return false if asked to serialize anything other than QueryExecution!",
testObj.isWriteable(QueryExecutionProvider.class, QueryExecutionProvider.class,
null, valueOf(WebContent.contentTypeResultsXML)));
assertFalse(
"RdfProvider.isWriteable() should return false to text/html!",
testObj.isWriteable(QueryExecution.class, QueryExecution.class, null,
TEXT_HTML_TYPE));

}
}
Expand Up @@ -75,7 +75,7 @@ public void testIsWriteable() {

@Test
public void testGetSize() {
assertEquals("Returned wrong size from HtmlProvider!", rdfProvider
assertEquals("Returned wrong size from RdfProvider!", rdfProvider
.getSize(null, null, null, null, null), -1);

}
Expand Down

0 comments on commit 0ad4c4b

Please sign in to comment.