Skip to content

Commit

Permalink
Add sparql service description for fcr:sparql GET requests.
Browse files Browse the repository at this point in the history
  • Loading branch information
lsitu authored and Andrew Woods committed Jul 27, 2014
1 parent 3004d09 commit 94b9e94
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 2 deletions.
Expand Up @@ -78,7 +78,7 @@ public abstract class RDFMediaType extends MediaType {
public final static MediaType JSON_LD_TYPE = typeFromString(JSON_LD);

public static final List<Variant> POSSIBLE_RDF_VARIANTS = mediaTypes(
TURTLE_TYPE, N3_TYPE, N3_ALT2_TYPE, RDF_XML_TYPE, NTRIPLES_TYPE, APPLICATION_XML_TYPE, TEXT_PLAIN_TYPE,
RDF_XML_TYPE, TURTLE_TYPE, N3_TYPE, N3_ALT2_TYPE, NTRIPLES_TYPE, APPLICATION_XML_TYPE, TEXT_PLAIN_TYPE,
TURTLE_X_TYPE, JSON_LD_TYPE).add().build();

public static final String POSSIBLE_RDF_RESPONSE_VARIANTS_STRING[] = {
Expand Down
Expand Up @@ -19,6 +19,8 @@
import com.google.common.base.Strings;
import com.hp.hpl.jena.query.ResultSet;
import org.apache.commons.io.IOUtils;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFLanguages;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
Expand All @@ -32,6 +34,7 @@
import org.fcrepo.kernel.impl.utils.LogoutCallback;
import org.fcrepo.transform.http.responses.ResultSetStreamingOutput;
import org.fcrepo.transform.sparql.JQLConverter;
import org.fcrepo.transform.sparql.SparqlServiceDescription;
import org.slf4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -59,7 +62,9 @@
import java.util.Properties;

import static com.google.common.util.concurrent.Futures.addCallback;
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
import static javax.ws.rs.core.MediaType.TEXT_HTML;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.status;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
Expand All @@ -75,10 +80,18 @@
import static org.apache.jena.riot.WebContent.contentTypeTextPlain;
import static org.apache.jena.riot.WebContent.contentTypeTextTSV;
import static org.apache.jena.riot.WebContent.contentTypeTurtle;
import static org.fcrepo.http.commons.domain.RDFMediaType.JSON_LD;
import static org.fcrepo.http.commons.domain.RDFMediaType.N3;
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_SPARQL_RDF_VARIANTS;
import static org.fcrepo.http.commons.domain.RDFMediaType.POSSIBLE_RDF_VARIANTS;
import static org.fcrepo.http.api.responses.BaseHtmlProvider.templateFilenameExtension;
import static org.fcrepo.http.api.responses.BaseHtmlProvider.templatesLocation;
import static org.fcrepo.http.api.responses.BaseHtmlProvider.velocityPropertiesLocation;
import static org.fcrepo.http.commons.domain.RDFMediaType.RDF_XML;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE_X;
import static org.slf4j.LoggerFactory.getLogger;

/**
Expand All @@ -97,6 +110,42 @@ public class FedoraSparql extends AbstractResource {

private static final Logger LOGGER = getLogger(FedoraSparql.class);

/**
* A stub method to return sparql service description for fcr:sparql GET
*
* @return
* @throws IOException
*/
@GET
@Timed
@Produces({RDF_XML, TURTLE, N3, N3_ALT2, NTRIPLES, TEXT_PLAIN, APPLICATION_XML, TURTLE_X, JSON_LD})
public Response sparqlServiceDescription(@Context final Request request,
@Context final UriInfo uriInfo)
throws IOException {

final SparqlServiceDescription sd = new SparqlServiceDescription(session, uriInfo);
final Variant bestPossibleResponse = request.selectVariant(POSSIBLE_RDF_VARIANTS);

LOGGER.debug("Getting sparql service description with media type {} ...", bestPossibleResponse);

Lang tmpLang;
if (bestPossibleResponse == null ||
(tmpLang = RDFLanguages.contentTypeToLang(bestPossibleResponse.getMediaType().toString())) == null) {
// set default format to rdf/xml
tmpLang = RDFLanguages.RDFXML;
}
final Lang rdfLang = tmpLang;
final StreamingOutput stream = new StreamingOutput() {
@Override
public void write(final OutputStream output) throws IOException {

LOGGER.debug("Writting sparql service description with jena RdfLanguages name {}.", rdfLang.getName());
final Writer outWriter = new OutputStreamWriter(output);
sd.createServiceDescription().asModel().write(outWriter, rdfLang.getName());
}
};
return ok(stream).header("Content-Type", rdfLang.getContentType().getContentType()).build();
}

/**
* A stub method so we can return a text/html representation using
Expand Down
@@ -0,0 +1,93 @@
/**
* Copyright 2014 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.transform.sparql;

import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
import static org.fcrepo.kernel.RdfLexicon.HAS_SPARQL_ENDPOINT;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;

import org.fcrepo.kernel.RdfLexicon;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.fcrepo.transform.http.FedoraSparql;

import javax.jcr.Session;
import javax.ws.rs.core.UriInfo;

/**
* Class to create service description for sparql endpoint
*
* @author lsitu
*/
public class SparqlServiceDescription {
private static final String SPARQL_FORMATS_NAMESPACE = "http://www.w3.org/ns/formats/";

private Session session;

private UriInfo uriInfo;

/**
* Constructor
* @param session
* @param uriInfo
*/
public SparqlServiceDescription(final Session session, final UriInfo uriInfo) {
this.session = session;
this.uriInfo = uriInfo;
}

/**
* Create sparql service description
* @return rdf model
*/
public RdfStream createServiceDescription() {
final Model model = ModelFactory.createDefaultModel();
// namespace prefixes use
model.setNsPrefix("rdf", RdfLexicon.RDF_NAMESPACE);
model.setNsPrefix("sd", RdfLexicon.SPARQL_SD_NAMESPACE);

final Resource s = model.createResource();
model.add(s, createProperty(RdfLexicon.RDF_NAMESPACE + "type"),
model.createResource(RdfLexicon.SPARQL_SD_NAMESPACE + "Service"));
model.add(s, HAS_SPARQL_ENDPOINT, model.createResource(
uriInfo.getBaseUriBuilder().path(FedoraSparql.class).build().toASCIIString()));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "supportedLanguage"),
model.createResource(RdfLexicon.SPARQL_SD_NAMESPACE + "SPARQL11Query"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "SPARQL_Results_TSV"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "SPARQL_Results_CSV"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "SPARQL_Results_JSON"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "SPARQL_Results_XML"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "Turtle"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "N3"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "N-Triples"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat"),
model.createResource(SPARQL_FORMATS_NAMESPACE + "RDF_XML"));
model.add(s, createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "feature"),
model.createResource(RdfLexicon.SPARQL_SD_NAMESPACE + "DereferencesURIs"));
final RdfStream rdfStream = RdfStream.fromModel(model);
rdfStream.session(session);
return rdfStream;
}
}
Expand Up @@ -27,6 +27,7 @@
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.jena.riot.RDFLanguages;
import org.fcrepo.integration.AbstractResourceIT;
import org.fcrepo.kernel.impl.FedoraResourceImpl;
import org.junit.After;
Expand Down Expand Up @@ -220,7 +221,6 @@ private String getResponseContent(final String sparql) throws IOException {
return content;
}


private String getFormRequestResponseContent(final String sparql)
throws IOException {
final HttpPost request = getFormRequest (sparql, "query");
Expand Down Expand Up @@ -340,4 +340,29 @@ public void testBadFormRequest() throws IOException {
response = client.execute(badRequest);
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatusLine().getStatusCode());
}

@Test
public void itShouldHaveDefaultRdfXmlServiceDescription() throws IOException {
final HttpGet request = new HttpGet(serverAddress + "/fcr:sparql");
request.addHeader("Accept", "*/*");
final HttpResponse response = client.execute(request);
assertEquals(200, response.getStatusLine().getStatusCode());
assertEquals(RDFLanguages.RDFXML.getContentType().getContentType(),
response.getFirstHeader("Content-Type").getValue());
final String content = EntityUtils.toString(response.getEntity());
assertTrue(content.contains("rdf:Description"));
}

@Test
public void itShouldHaveTurtleServiceDescription() throws IOException {
final String format = "text/turtle";
final HttpGet request = new HttpGet(serverAddress + "/fcr:sparql");
request.addHeader("Accept", format);
final HttpResponse response = client.execute(request);
assertEquals(200, response.getStatusLine().getStatusCode());
assertEquals(format,
response.getFirstHeader("Content-Type").getValue());
final String content = EntityUtils.toString(response.getEntity());
assertTrue(content.contains("@prefix"));
}
}
@@ -0,0 +1,73 @@
/**
* Copyright 2014 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.transform.sparql;

import com.hp.hpl.jena.rdf.model.Model;
import org.fcrepo.http.commons.test.util.TestHelpers;
import org.fcrepo.kernel.RdfLexicon;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;

import static org.mockito.MockitoAnnotations.initMocks;

import javax.jcr.Session;
import javax.ws.rs.core.UriInfo;

import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
import static org.fcrepo.kernel.RdfLexicon.HAS_SPARQL_ENDPOINT;
import static org.fcrepo.kernel.RdfLexicon.SPARQL_SD_NAMESPACE;
import static org.junit.Assert.assertTrue;

/**
* <p>SparqlServiceDescriptionTest class.</p>
*
* @author lsitu
*/
public class SparqlServiceDescriptionTest {
private SparqlServiceDescription testObj;

private UriInfo uriInfo;

@Mock
Session mockSession;

@Before
public void setUp() {
initMocks(this);

uriInfo = TestHelpers.getUriInfoImpl();
testObj = new SparqlServiceDescription(mockSession, uriInfo);
}

@Test
public void shouldGenerateServiceDescriptionRdf() {
final RdfStream rdfStream = testObj.createServiceDescription();
final Model model = rdfStream.asModel();
assertTrue(model.listStatements().toList().size() > 0);
assertTrue(model.listResourcesWithProperty(
createProperty(RdfLexicon.RDF_NAMESPACE + "type"),
createProperty(SPARQL_SD_NAMESPACE + "Service")).hasNext());
assertTrue(model.listResourcesWithProperty(HAS_SPARQL_ENDPOINT).hasNext());
assertTrue(model.listResourcesWithProperty(
createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "supportedLanguage")).hasNext());
assertTrue(model.listResourcesWithProperty(
createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "resultFormat")).hasNext());
assertTrue(model.listResourcesWithProperty(
createProperty(RdfLexicon.SPARQL_SD_NAMESPACE + "feature")).hasNext());
}
}

0 comments on commit 94b9e94

Please sign in to comment.