blob: ee6d6a6cbb4932bbb5b591c04889045136cf7427 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you 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.apache.stanbol.commons.jsonld.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.commons.rdf.Graph;
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 JsonLdSerializingProvider 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=""), //none (keep the default)
@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
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, Graph tc, String formatIdentifier) {
ClerezzaRDFParser serializer = new ClerezzaRDFParser();
try {
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);
}
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 (JsonLdError e) {
throw new RuntimeException(e.getMessage(), e);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Activate
protected void activate(ComponentContext ctx) {
opts = new JsonLdOptions();
@SuppressWarnings("unchecked")
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
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;
}
}
}