Skip to content
Merged
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
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ JSONLD-Java Clerezza Integration module
[![Build Status](https://travis-ci.org/jsonld-java/jsonld-java-clerezza.svg?branch=master)](https://travis-ci.org/jsonld-java/jsonld-java-clerezza)
[![Coverage Status](https://coveralls.io/repos/jsonld-java/jsonld-java-clerezza/badge.svg?branch=master)](https://coveralls.io/r/jsonld-java/jsonld-java-clerezza?branch=master)

This module provide a `ParsingProvider`and `SerializingProvider` for Apache Clerezza. Those Providers plug into the Clerezza `Parser` and `Serializer` service infrastructure. Meaning that adding this bundle will allow Clerezza to parse and serialize JSON-LD.

USAGE
=====

Expand All @@ -24,3 +26,32 @@ ClerezzaTripleCallback
The ClerezzaTripleCallback returns an instance of `org.apache.clerezza.rdf.core.MGraph`

See [ClerezzaTripleCallbackTest.java](./src/test/java/com/github/jsonldjava/clerezza/ClerezzaTripleCallbackTest.java) for example Usage.


From OSGI
---------

Assuming the above Bundle is active in the OSGI Environment one can simple inject the `Serializer` and/or `Parser` service.

@Reference
private Serializer serializer;

@Reference
private Parser parser;


Normal Java
-----------

Both the `Parser` and `Serializer` also support `java.util.ServiceLoader`. So when running outside an OSGI environment one can use the `getInstance()` to obtain an instance.

Serializer serializer = Serializer.getInstance();

Parser parser = Parser.getInstance();

Supported Formats
-----------------

The JSON-LD parser implementation supports `application/ld+json`. The serializer supports both `application/ld+json` and `application/json`.

The rational behind this is that the parser can not parse any JSON however the Serializer does generate valid JSON.
63 changes: 61 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<developer>
<name>Peter Ansell</name>
</developer>
<developer>
<name>Rupert Westenthaler</name>
</developer>
</developers>

<properties>
Expand All @@ -36,6 +39,19 @@
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.clerezza</groupId>
<artifactId>rdf.core</artifactId>
<version>${clerezza.version}</version>
</dependency>
<!-- OSGI related -->
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.12</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jsonld-java</artifactId>
Expand All @@ -45,8 +61,9 @@
</dependency>
<dependency>
<groupId>org.apache.clerezza</groupId>
<artifactId>rdf.core</artifactId>
<version>${clerezza.version}</version>
<artifactId>rdf.ontologies</artifactId>
<version>0.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
Expand Down Expand Up @@ -74,6 +91,48 @@
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<inherited>true</inherited>
<configuration>
<instructions>
<Bundle-DocURL>https://github.com/jsonld-java/jsonld-java-clerezza</Bundle-DocURL>
<Bundle-Vendor>JSONLD-JAVA Clerezza Integration</Bundle-Vendor>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<_versionpolicy>$${version;===;${@}}</_versionpolicy>
<_provider-policy>[$(version;===;$(@)),$(version;=+;$(@)))</_provider-policy>
<_consumer-policy>[$(version;===;$(@)),$(version;+;$(@)))</_consumer-policy>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.21.0</version>
<!-- slf4j impl is needed when QDox inspects/loads classes that use a
static field for the logger, so that those classes can be loaded. -->
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
<configuration>
<properties>
<service.vendor>JSONLD-JAVA</service.vendor>
</properties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.github.jsonldjava.clerezza;

import java.io.IOException;
import java.io.InputStream;

import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.serializedform.ParsingProvider;
import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.jsonldjava.core.JsonLdError;
import com.github.jsonldjava.core.JsonLdProcessor;
import com.github.jsonldjava.utils.JsonUtils;

/**
* A {@link org.apache.clerezza.rdf.core.serializedform.ParsingProvider} for
* JSON-LD (application/ld+json) based on the java-jsonld library
*
* @author Rupert Westenthaler
*
*/
@Component(immediate = true, policy = ConfigurationPolicy.OPTIONAL)
@Service
@SupportedFormat("application/ld+json")
public class ClerezzaJsonLdParsingProvider implements ParsingProvider {

private final Logger logger = LoggerFactory.getLogger(getClass());

@Override
public void parse(MGraph target, InputStream serializedGraph, String formatIdentifier,
UriRef baseUri) {
// The callback will add parsed triples to the target MGraph
final ClerezzaTripleCallback ctc = new ClerezzaTripleCallback();
ctc.setMGraph(target);
Object input;
int startSize = 0;
if (logger.isDebugEnabled()) {
startSize = target.size();
}
final long start = System.currentTimeMillis();
try {
input = JsonUtils.fromInputStream(serializedGraph, "UTF-8");
} catch (final IOException e) {
logger.error("Unable to read from the parsed input stream", e);
throw new RuntimeException(e.getMessage(), e);
}
try {
JsonLdProcessor.toRDF(input, ctc);
} catch (final JsonLdError e) {
logger.error("Unable to parse JSON-LD from the parsed input stream", e);
throw new RuntimeException(e.getMessage(), e);
}
if (logger.isDebugEnabled()) {
logger.debug(" - parsed {} triples in {}ms", target.size() - startSize,
System.currentTimeMillis() - start);
}
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package com.github.jsonldjava.clerezza;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.clerezza.rdf.core.TripleCollection;
import org.apache.clerezza.rdf.core.serializedform.SerializingProvider;
import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyOption;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.jsonldjava.core.JsonLdError;
import com.github.jsonldjava.core.JsonLdOptions;
import com.github.jsonldjava.core.JsonLdProcessor;
import com.github.jsonldjava.utils.JsonUtils;

/**
* A {@link org.apache.clerezza.rdf.core.serializedform.SerializingProvider} for
* JSON-LD (application/ld+json) based on the java-jsonld library
*
* @author Rupert Westenthaler
*/
@Component(immediate = true, policy = ConfigurationPolicy.OPTIONAL)
@Service
@SupportedFormat(value = { "application/ld+json", "application/json" })
public class ClerezzaJsonLdSerializingProvider implements SerializingProvider {

private final Logger logger = LoggerFactory.getLogger(getClass());

private static final Charset UTF8 = Charset.forName("UTF-8");

private static final String MODE_EXPAND = "expand";
private static final String MODE_FLATTEN = "flatten";
private static final String MODE_COMPACT = "compact";

@Property(value = "", options = {
@PropertyOption(value = "%mode.option.none", name = ""),
@PropertyOption(value = "%mode.option.flatten", name = "flatten"),
@PropertyOption(value = "%mode.option.compact", name = "compact"),
@PropertyOption(value = "%mode.option.expand", name = MODE_EXPAND) })
private static final String PROP_MODE = "mode";

@Property(boolValue = false)
private static final String PROP_USE_RDF_TYPE = "useRdfTye";

@Property(boolValue = false)
private static final String PROP_USE_NATIVE_TYPES = "useNativeTypes";

@Property(boolValue = true)
private static final String PROP_PRETTY_PRINT = "prettyPrint";

// TODO: make configurable or read the whole prefix.cc list from a file and
// search for really used namespaces while parsing the triples in the
// ClerezzaRDFParser
private static Map<String, String> DEFAULT_NAMESPACES;
static {
// core ontologies, top from prefixcc and some stanbol specific
final Map<String, String> ns = new LinkedHashMap<String, String>();
// core schemas
ns.put("xsd", "http://www.w3.org/2001/XMLSchema#");
ns.put("owl", "http://www.w3.org/2002/07/owl#");
ns.put("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
ns.put("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
// well known ontologies
ns.put("skos", "http://www.w3.org/2004/02/skos/core#");
ns.put("geo", "http://www.w3.org/2003/01/geo/wgs84_pos#");
ns.put("dc", "http://purl.org/dc/elements/1.1/");
ns.put("foaf", "http://xmlns.com/foaf/0.1/");
ns.put("ma", "http://www.w3.org/ns/ma-ont#");
// big datasets
ns.put("dbo", "http://dbpedia.org/ontology/");
ns.put("dbp", "http://dbpedia.org/property/");
ns.put("yago", "http://yago-knowledge.org/resource/");
ns.put("fb", "http://rdf.freebase.com/ns/");
ns.put("geonames", "http://www.geonames.org/ontology#");
// stanbol specific
ns.put("fise", "http://fise.iks-project.eu/ontology/");
ns.put("enhancer", "http://stanbol.apache.org/ontology/enhancer/enhancer#");
ns.put("entityhub", "http://stanbol.apache.org/ontology/entityhub/entityhub#");

DEFAULT_NAMESPACES = Collections.unmodifiableMap(ns);
}

private JsonLdOptions opts = null;
private String mode;

private boolean prettyPrint;

@Override
public void serialize(OutputStream serializedGraph, TripleCollection tc, String formatIdentifier) {
final ClerezzaRDFParser serializer = new ClerezzaRDFParser();
try {
final long start = System.currentTimeMillis();
Object output = JsonLdProcessor.fromRDF(tc, serializer);

if (MODE_EXPAND.equalsIgnoreCase(mode)) {
logger.debug(" - mode: {}", MODE_EXPAND);
output = JsonLdProcessor.expand(output, opts);
}
if (MODE_FLATTEN.equalsIgnoreCase(mode)) {
logger.debug(" - mode: {}", MODE_FLATTEN);
// TODO: Allow inframe config
final Object inframe = null;
output = JsonLdProcessor.flatten(output, inframe, opts);
}
if (MODE_COMPACT.equalsIgnoreCase(mode)) {
logger.debug(" - mode: {}", MODE_COMPACT);
// TODO: collect namespaces used in the triples in the
// ClerezzaRDFParser
final Map<String, Object> localCtx = new HashMap<String, Object>();
localCtx.put("@context", DEFAULT_NAMESPACES);
output = JsonLdProcessor.compact(output, localCtx, opts);
}
final Writer writer = new OutputStreamWriter(serializedGraph, UTF8);
logger.debug(" - prettyPrint: {}", prettyPrint);
if (prettyPrint) {
JsonUtils.writePrettyPrint(writer, output);
} else {
JsonUtils.write(writer, output);
}
if (logger.isDebugEnabled()) {
logger.debug(" - serialized {} triples in {}ms", serializer.getCount(),
System.currentTimeMillis() - start);
}
} catch (final JsonLdError e) {
throw new RuntimeException(e.getMessage(), e);
} catch (final IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}

@Activate
protected void activate(ComponentContext ctx) {
opts = new JsonLdOptions();
@SuppressWarnings("unchecked")
final Dictionary<String, Object> config = ctx.getProperties();
// boolean properties
opts.setUseRdfType(getState(config.get(PROP_USE_RDF_TYPE), false));
opts.setUseNativeTypes(getState(config.get(PROP_USE_NATIVE_TYPES), false));
prettyPrint = getState(config.get(PROP_PRETTY_PRINT), true);
// parse the string mode
final Object value = config.get(PROP_MODE);
mode = value == null ? null : value.toString();
}

@Deactivate
protected void deactivate(ComponentContext ctx) {
opts = null;
mode = null;
prettyPrint = false;
}

/**
* @param value
*/
private boolean getState(Object value, boolean defaultState) {
if (value instanceof Boolean) {
return ((Boolean) value).booleanValue();
} else if (value != null) {
return Boolean.parseBoolean(value.toString());
} else {
return defaultState;
}
}

}

Loading