Skip to content
This repository has been archived by the owner on Oct 12, 2021. It is now read-only.

New UniversalResourceSingleProvider to support more RDF formats #9

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,58 @@
*******************************************************************************/
package org.eclipse.lyo.oslc4j.core.model;

import javax.print.attribute.standard.Media;
import javax.ws.rs.core.MediaType;

public interface OslcMediaType {

public final static String APPLICATION = "application";
public final static String TEXT = "text";
String APPLICATION_RDF_XML = "application/rdf+xml";
MediaType APPLICATION_RDF_XML_TYPE = MediaType.valueOf(APPLICATION_RDF_XML);

public final static String RDF_XML = "rdf+xml";
public final static String APPLICATION_RDF_XML = APPLICATION + "/" + RDF_XML;
public final static MediaType APPLICATION_RDF_XML_TYPE = new MediaType(APPLICATION, RDF_XML);
String APPLICATION_JSON_LD = "application/ld+json";
MediaType APPLICATION_JSON_LD_TYPE = MediaType.valueOf(APPLICATION_JSON_LD);

public final static String JSON_LD = "ld+json";
public final static String APPLICATION_JSON_LD = APPLICATION + "/" + JSON_LD;
public final static MediaType APPLICATION_JSON_LD_TYPE = new MediaType(APPLICATION, JSON_LD);
String TEXT_TURTLE = "text/turtle";
MediaType TEXT_TURTLE_TYPE = MediaType.valueOf(TEXT_TURTLE);

public final static String APPLICATION_JSON = MediaType.APPLICATION_JSON;
public final static MediaType APPLICATION_JSON_TYPE = MediaType.APPLICATION_JSON_TYPE;
String RDF_JSON_MIME = "application/rdf+json";
MediaType RDF_JSON_MT = MediaType.valueOf(RDF_JSON_MIME);

public final static String APPLICATION_XML = MediaType.APPLICATION_XML;
public final static MediaType APPLICATION_XML_TYPE = MediaType.APPLICATION_XML_TYPE;
String N_TRIPLES_MIME = "application/n-triples";
MediaType N_TRIPLES_MT = MediaType.valueOf(N_TRIPLES_MIME);

public final static String TEXT_XML = MediaType.TEXT_XML;
public final static MediaType TEXT_XML_TYPE = MediaType.TEXT_XML_TYPE;
// OSLC specific serialisations

public final static String TURTLE="turtle";
public final static String TEXT_TURTLE = TEXT + "/" + TURTLE;
public final static MediaType TEXT_TURTLE_TYPE = new MediaType(TEXT, TURTLE);
String APPLICATION_X_OSLC_COMPACT_XML = "application" + "/" + "x-oslc-compact+xml";
MediaType APPLICATION_X_OSLC_COMPACT_XML_TYPE = new MediaType("application",
"x-oslc-compact+xml");

public final static String X_OSLC_COMPACT_XML = "x-oslc-compact+xml";
public final static String APPLICATION_X_OSLC_COMPACT_XML = APPLICATION + "/" + X_OSLC_COMPACT_XML;
public final static MediaType APPLICATION_X_OSLC_COMPACT_XML_TYPE = new MediaType(APPLICATION, X_OSLC_COMPACT_XML);
String APPLICATION_X_OSLC_COMPACT_JSON = "application/x-oslc-compact+json";
MediaType APPLICATION_X_OSLC_COMPACT_JSON_TYPE = new MediaType("application",
"x-oslc-compact+json");

// Non-standard RDF serialisations

String APPLICATION_JSON = MediaType.APPLICATION_JSON;
MediaType APPLICATION_JSON_TYPE = MediaType.APPLICATION_JSON_TYPE;

String APPLICATION_XML = MediaType.APPLICATION_XML;
MediaType APPLICATION_XML_TYPE = MediaType.APPLICATION_XML_TYPE;

String TEXT_XML = MediaType.TEXT_XML;
MediaType TEXT_XML_TYPE = MediaType.TEXT_XML_TYPE;

String RDF_THRIFT_MIME = "application/rdf+thrift";
MediaType RDF_THRIFT_MT = MediaType.valueOf(RDF_THRIFT_MIME);

// Deprecated

@Deprecated String APPLICATION = "application";
@Deprecated String TEXT = "text";
@Deprecated String RDF_XML = "rdf+xml";
@Deprecated String JSON_LD = "ld+json";
@Deprecated String TURTLE = "turtle";
@Deprecated String X_OSLC_COMPACT_XML = "x-oslc-compact+xml";
@Deprecated String X_OSLC_COMPACT_JSON = "x-oslc-compact+json";

public final static String X_OSLC_COMPACT_JSON = "x-oslc-compact+json"; // TODO - Compact media type never defined in the OSLC spec for JSON
public final static String APPLICATION_X_OSLC_COMPACT_JSON = APPLICATION + "/" + X_OSLC_COMPACT_JSON;
public final static MediaType APPLICATION_X_OSLC_COMPACT_JSON_TYPE = new MediaType(APPLICATION, X_OSLC_COMPACT_JSON);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractOslcRdfXmlProvider
public abstract class AbstractOslcRdfXmlProvider extends AbstractRdfProvider
{
private static final Logger log = LoggerFactory.getLogger(AbstractOslcRdfXmlProvider.class.getName
());
Expand All @@ -78,9 +78,9 @@ public abstract class AbstractOslcRdfXmlProvider
@Deprecated
public static final String OSLC4J_STRICT_DATATYPES = "org.eclipse.lyo.oslc4j.strictDatatypes";

private static final Annotation[] ANNOTATIONS_EMPTY_ARRAY = new Annotation[0];
private static final Class<Error> CLASS_OSLC_ERROR = Error.class;
private static final ErrorHandler ERROR_HANDLER = new ErrorHandler();
protected static final Annotation[] ANNOTATIONS_EMPTY_ARRAY = new Annotation[0];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

protected static final Class<Error> CLASS_OSLC_ERROR = Error.class;
protected static final ErrorHandler ERROR_HANDLER = new ErrorHandler();

private @Context HttpHeaders httpHeaders; // Available only on the server
protected @Context HttpServletRequest httpServletRequest; // Available only on the server
Expand Down Expand Up @@ -193,68 +193,6 @@ private RDFWriter getRdfWriter(final String serializationLanguage, final Model m
return writer;
}

protected void writeTo(final boolean queryResult,
final Object[] objects,
final MediaType baseMediaType,
final MultivaluedMap<String, Object> map,
final OutputStream outputStream)
throws WebApplicationException
{
boolean isClientSide = false;

try {
httpServletRequest.getMethod();
} catch (RuntimeException e) {
isClientSide = true;
}

String descriptionURI = null;
String responseInfoURI = null;

if (queryResult && ! isClientSide)
{

final String method = httpServletRequest.getMethod();
if ("GET".equals(method))
{
descriptionURI = OSLC4JUtils.resolveURI(httpServletRequest,true);
responseInfoURI = descriptionURI;

final String queryString = httpServletRequest.getQueryString();
if ((queryString != null) &&
(isOslcQuery(queryString)))
{
responseInfoURI += "?" + queryString;
}
}

}

final String serializationLanguage = getSerializationLanguage(baseMediaType);

@SuppressWarnings("unchecked")
final Map<String, Object> properties = isClientSide ?
null :
(Map<String, Object>)httpServletRequest.getAttribute(OSLC4JConstants.OSLC4J_SELECTED_PROPERTIES);
final String nextPageURI = isClientSide ?
null :
(String)httpServletRequest.getAttribute(OSLC4JConstants.OSLC4J_NEXT_PAGE);
final Integer totalCount = isClientSide ?
null :
(Integer)httpServletRequest.getAttribute(OSLC4JConstants.OSLC4J_TOTAL_COUNT);

ResponseInfo<?> responseInfo = new ResponseInfoArray<Object>(null, properties, totalCount, nextPageURI);

writeObjectsTo(
objects,
outputStream,
properties,
descriptionURI,
responseInfoURI,
responseInfo,
serializationLanguage
);
}

private String getSerializationLanguage(final MediaType baseMediaType) {
// Determine whether to serialize in xml or abreviated xml based upon mediatype.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package org.eclipse.lyo.oslc4j.provider.jena;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

license


import java.io.InputStream;
import java.io.OutputStream;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.RDFReader;
import org.apache.jena.rdf.model.RDFWriter;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.riot.RDFFormat;
import org.apache.jena.riot.RDFLanguages;
import org.apache.jena.util.FileUtils;
import org.eclipse.lyo.oslc4j.core.exception.MessageExtractor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Created on 2018-05-27
*
* @author Andrew Berezovskyi ([email protected])
* @version $version-stub$
* @since 0.0.1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since 4.0.0

*/
public class AbstractRdfProvider {

private final static Logger log = LoggerFactory.getLogger(AbstractRdfProvider.class);

protected void writeTo(final boolean queryResult, final Object[] objects,
final MediaType baseMediaType, final MultivaluedMap<String, Object> map,
final OutputStream outputStream) throws WebApplicationException {
String descriptionURI = null;
String responseInfoURI = null;

if (queryResult) {
throw new IllegalArgumentException("Query Result resources have to be constructed "
+ "before marshalling");
}

writeNonQueryObjectsTo(objects, outputStream, baseMediaType);
}

protected void writeNonQueryObjectsTo(final Object[] objects, final OutputStream outputStream,
final MediaType serializationLanguage) {
try {
final Model model = JenaModelHelper.createJenaModel(objects);

RDFWriter writer = getRdfWriter(serializationLanguage.toString(), model);

if (serializationLanguage.equals(FileUtils.langXML) || serializationLanguage.equals(
FileUtils.langXMLAbbrev)) {
// XML (and Jena) default to UTF-8, but many libs default to ASCII, so need
// to set this explicitly
writer.setProperty("showXmlDeclaration", "false");
String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
outputStream.write(xmlDeclaration.getBytes());
}
writer.write(model, outputStream, null);
} catch (final Exception exception) {
log.warn(MessageExtractor.getMessage("ErrorSerializingResource"), exception);
// TODO Andrew@2018-03-03: use another exception
throw new WebApplicationException(exception);
}
}

private RDFWriter getRdfWriter(final String serializationLanguage, final Model model) {
RDFWriter writer = null;
if (serializationLanguage.equals(FileUtils.langXMLAbbrev)) {
// TODO Andrew@2018-05-27: do this for the RDF/XML-ABBREV only iff the users want it
/* Personally, I don't like the idea of maintaining a separate ABBREV writer. I think
we need to start introducing some flags where users can disable legacy functionality
altogether and rely on Jena etc.*/
writer = new RdfXmlAbbreviatedWriter();
} else {
final Lang lang = RDFLanguages.nameToLang(serializationLanguage);
// RDFDataMgr.createGraphWriter(mapLang(lang));
// final Graph graph = model.getGraph();
writer = model.getWriter(lang.getName());
// FIXME Andrew@2018-05-27: what's the purpose of name>lang>name conversion?
}
return writer;
}

private RDFFormat mapLang(final Lang lang) {
// TODO Andrew@2018-05-27: allow configuration from users (compact vs pretty etc)
final RDFFormat rdfFormat = new RDFFormat(lang);
return rdfFormat;
}

/*=== READER ================================*/

protected Object[] readFrom(final Class<?> type, final MediaType mediaType, final InputStream
inputStream)
throws WebApplicationException {
final Model model = ModelFactory.createDefaultModel();
RDFDataMgr.read(
model,
inputStream,
RDFDataMgr.determineLang(null, mediaType.toString(), null));
try {
return JenaModelHelper.fromJenaModel(model, type);
} catch (final Exception exception) {
// FIXME Andrew@2018-05-27: we shall just stop the JMH blanket of exceptions craziness
throw new RuntimeException(exception);
// throw new WebApplicationException(exception, buildBadRequestResponse(exception,
// mediaType,
// map));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.Provider;
import org.eclipse.lyo.oslc4j.core.model.OslcMediaType;

/**
* Created on 2018-03-03
Expand All @@ -13,6 +12,6 @@
* @since 0.0.1
*/
@Provider
@Produces({OslcMediaType.JSON_LD})
@Consumes({OslcMediaType.JSON_LD})
@Produces({"ld+json"})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a MIME type and a const

@Consumes({"ld+json"})
public class OslcJsonLdProvider extends OslcRdfXmlProvider{ }
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.eclipse.lyo.oslc4j.provider.jena;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

license


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import org.eclipse.lyo.oslc4j.core.model.IResource;
import org.eclipse.lyo.oslc4j.core.model.OslcMediaType;

/**
* JMH accepts objects in general but there is a slight conflict in the JAX pipeline with the
* Collections and Arrays, which are technically also Objects. If someone needs raw Objects, they
* can use old Providers.
*
* @author Andrew Berezovskyi ([email protected])
* @version $version-stub$
* @since 0.0.1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since 4.0.0

*/
@Provider
@Produces({OslcMediaType.APPLICATION_JSON_LD, OslcMediaType.TEXT_TURTLE, OslcMediaType
.N_TRIPLES_MIME, OslcMediaType.RDF_JSON_MIME, OslcMediaType.RDF_THRIFT_MIME})
@Consumes({OslcMediaType.APPLICATION_JSON_LD, OslcMediaType.TEXT_TURTLE, OslcMediaType
.N_TRIPLES_MIME, OslcMediaType.RDF_JSON_MIME, OslcMediaType.RDF_THRIFT_MIME})
public class UniversalResourceSingleProvider extends AbstractRdfProvider implements
MessageBodyReader<IResource>, MessageBodyWriter<IResource>
{

private final int CANNOT_BE_DETERMINED_IN_ADVANCE = -1;

@Override
public boolean isReadable(final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
// TODO Andrew@2018-05-27: test it
return true;
}

@Override
public IResource readFrom(final Class<IResource> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType,
final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream)
throws IOException, WebApplicationException {
final Object[] objects = readFrom(type, mediaType, entityStream);
if(objects.length > 1) {
throw new IllegalArgumentException("Can't unmarshal a single resource from a model "
+ "with multiple matching resources");
}
final IResource resource = (IResource) objects[0];
return resource;
}

@Override
public boolean isWriteable(final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
// TODO Andrew@2018-05-27: test
return true;
}

@Override
public long getSize(final IResource iResource, final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType) {
return CANNOT_BE_DETERMINED_IN_ADVANCE;
}

@Override
public void writeTo(final IResource iResource, final Class<?> type, final Type genericType,
final Annotation[] annotations, final MediaType mediaType,
final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
throws IOException, WebApplicationException {
writeNonQueryObjectsTo(new Object[] {iResource}, entityStream, mediaType);
}
}
Loading