package org.aksw.sparqlify.platform.config;
import java.io.File;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.aksw.jena_sparql_api.core.QueryExecutionFactory;
import org.aksw.jena_sparql_api.exprs_ext.E_StrConcatPermissive;
import org.aksw.jena_sparql_api.views.Constraint;
import org.aksw.jena_sparql_api.views.SparqlifyConstants;
import org.aksw.sparqlify.config.syntax.Config;
import org.aksw.sparqlify.config.syntax.ViewDefinition;
import org.aksw.sparqlify.database.PrefixConstraint;
import org.apache.jena.graph.Node;
import org.apache.jena.rdf.model.AnonId;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.core.VarExprList;
import org.apache.jena.sparql.expr.E_StrConcat;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprFunction;
import org.apache.jena.vocabulary.RDF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.fuberlin.wiwiss.pubby.Configuration;
import de.fuberlin.wiwiss.pubby.DataSourceRegistry;
import de.fuberlin.wiwiss.pubby.vocab.CONF;
public class PubbyConfigFactory {
public static Resource pubbySparqlEndpoint = ResourceFactory.createResource("urn://sparqlify/platform/pubby/sparql");
private static final Logger logger = LoggerFactory.getLogger(PubbyConfigFactory.class);
private String baseUri;
private String contextPath;
private String projectName = "";
private String projectHomepage = "";
private File baseConfigFile;
private Config sparqlifyConfig;
private QueryExecutionFactory queryExecutionFactory;
//"BaseServlet.serverConfiguration"
public String getContextPath() {
return contextPath;
}
public void setContextPath(String contextPath) {
this.contextPath = contextPath;
}
public PubbyConfigFactory() {
}
public QueryExecutionFactory getQueryExecutionFactory() {
return queryExecutionFactory;
}
public void setQueryExecutionFactory(QueryExecutionFactory queryExecutionFactory) {
this.queryExecutionFactory = queryExecutionFactory;
}
public void setBaseConfigFile(File file) {
this.baseConfigFile = file;
}
public File getBaseConfigFile() {
return baseConfigFile;
}
/*
public void setOverlayModel(Model model) {
this.overlayModel = model;
}
public Model getOverlayModel() {
return overlayModel;
}
*/
public Config getSparqlifyConfig() {
return sparqlifyConfig;
}
public void setSparqlifyConfig(Config sparqlifyConfig) {
this.sparqlifyConfig = sparqlifyConfig;
}
public String getBaseUri() {
return baseUri;
}
public void setBaseUri(String baseUri) {
this.baseUri = baseUri;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getProjectHomepage() {
return projectHomepage;
}
public void setProjectHomepage(String projectHomepage) {
this.projectHomepage = projectHomepage;
}
public String extractPrefix(Expr expr) {
if(expr instanceof E_StrConcatPermissive || expr instanceof E_StrConcat) {
ExprFunction fn = expr.getFunction();
List<Expr> args = fn.getArgs();
if(args.size() == 0) {
logger.warn("Zero argument concat expression detected: " + expr);
} else {
Expr first = args.get(0);
if(first.isConstant()) {
String value = first.getConstant().asUnquotedString();
return value;
}
}
}
return null;
}
public Set<String> getKnownPrefixes(Var var, ViewDefinition viewDef) {
Set<String> result = new HashSet<String>();
if(viewDef.getConstraints() != null) {
for(Constraint constraint : viewDef.getConstraints()) {
if(constraint instanceof PrefixConstraint) {
PrefixConstraint c = (PrefixConstraint)constraint;
if(var.equals(c.getVar())) {
result.addAll(c.getPrefixes().getSet());
}
}
}
}
VarExprList vel = viewDef.getViewTemplateDefinition().getVarExprList();
Expr expr = vel.getExpr(var);
// We expect the expression to be a term constructor
if(expr.isFunction()) {
ExprFunction termCtor = expr.getFunction();
if(termCtor.getFunctionIRI().equals(SparqlifyConstants.uriLabel)) {
List<Expr> args = termCtor.getArgs();
if(args.size() == 0) {
logger.warn("Zero length term constructor for var " + var + " in view definition" + viewDef.getName());
} else {
Expr arg = args.get(0);
String prefix = extractPrefix(arg);
if(prefix != null) {
result.add(prefix);
}
}
}
}
return result;
}
public Set<String> getKnownPrefixes(ViewDefinition viewDef) {
Set<String> result = new HashSet<String>();
Set<Node> nodes = new HashSet<Node>();
for(Quad quad : viewDef.getConstructPattern()) {
nodes.add(quad.getSubject());
}
for(Node node : nodes) {
if(node.isVariable()) {
Set<String> prefixes = getKnownPrefixes((Var)node, viewDef);
result.addAll(prefixes);
} else if(node.isURI()) {
result.add(node.getURI());
}
}
return result;
}
public Set<String> getKnownPrefixes(Config sparqlifyConfig) {
Set<String> result = new HashSet<String>();
for(ViewDefinition viewDef : sparqlifyConfig.getViewDefinitions()) {
Set<String> prefixes = getKnownPrefixes(viewDef);
result.addAll(prefixes);
}
return result;
}
public static Set<String> extractHostNames(Set<String> prefixes) {
Set<String> result = new HashSet<String>();
for(String prefix : prefixes) {
try {
URL url = new URL(prefix);
String hostname = url.getProtocol() + "://" + url.getHost(); // + "/";
result.add(hostname);
} catch(Exception e) {
logger.warn("Failed to extract hostname from: [" + prefix +"]");
}
}
return result;
}
public void autoconfigure(Model model, Resource config) {
Set<String> prefixes = getKnownPrefixes(sparqlifyConfig);
Set<String> hostnames = PubbyConfigFactory.extractHostNames(prefixes);
System.out.println("Prefixes: " + prefixes);
System.out.println("Hostnames: " + hostnames);
for(String hostname : hostnames) {
writeDatasetDesc(model, config, hostname);
}
}
public void writeDatasetDesc(Model model, Resource parentConfig, String prefix) {
Resource dataset = model.createResource(new AnonId());
Resource datasetBase = model.createResource(prefix + contextPath);
model.add(parentConfig, CONF.dataset, dataset);
//Resource pubbySparqlEndpoint = model.createResource(baseUri + "sparql");
//PubbyConfigFactory.
model.add(dataset, CONF.sparqlEndpoint, pubbySparqlEndpoint);
model.add(dataset, CONF.datasetBase, datasetBase);
model.add(dataset, CONF.fixUnescapedCharacters, model.createLiteral("(),'!$&*+;=@"));
/*
# conf:dataset [
# conf:sparqlEndpoint <http://localhost:7531/sparql>;
# conf:sparqlDefaultGraph <http://example.org>;
# conf:datasetBase <http://your-dataset-namespace.org/>;
# conf:fixUnescapedCharacters "(),'!$&*+;=@";
# ];
*/
}
// TODO Do not call this method more than once; it will register a datasource with the same name again
public Configuration create() {
//Model baseModel = FileManager.get().loadModel(baseConfigFile.getAbsoluteFile().toURI().toString());
// TODO: We need to register a new sparql datasource with each call!
QefDataSource dataSource = new QefDataSource(queryExecutionFactory, pubbySparqlEndpoint.getURI());
DataSourceRegistry.getInstance().put(pubbySparqlEndpoint.getURI(), dataSource);
/*
for(int i = 0; i < 15; ++i) {
System.out.println("__________________________________________________________" + this.getClass().getName());
}
*/
//Model model = baseModel;
Model model = ModelFactory.createDefaultModel();
model.setNsPrefixes(sparqlifyConfig.getPrefixMapping());
Resource config = model.createResource("urn://sparqlify/platform/pubby/config");
model.add(config, RDF.type, CONF.Configuration);
model.add(config, CONF.webBase, model.createResource(baseUri));
model.add(config, CONF.projectName, model.createLiteral(projectName));
model.add(config, CONF.projectHomepage, model.createResource(projectHomepage));
autoconfigure(model, config);
System.out.println("Pubby configuration:");
System.out.println("-----------------------------------------------");
model.write(System.out, "TURTLE");
System.out.println("-----------------------------------------------");
Configuration result = new Configuration(model);
return result;
}
}