jenkins-bot has submitted this change and it was merged.
Change subject: Implement LDF server for Blazegraph
......................................................................
Implement LDF server for Blazegraph
Change-Id: I78b4edd4d725d2b87cfead92a35b31b072f31b40
Bug: T136358
---
M blazegraph/pom.xml
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BigdataStatementToJenaStatementMapper.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPF.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPFRequestProcessor.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSource.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSourceType.java
A blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/LDFServlet.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TPFRequestParserForBlazegraph.java
A
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TriplePatternElementParserForBlazegraph.java
A dist/src/script/ldf-config.json
M dist/src/script/runBlazegraph.sh
M docs/ChangeLog
M pom.xml
M war/pom.xml
M war/src/assembly/dist.xml
M war/src/config/web.xml
16 files changed, 881 insertions(+), 8 deletions(-)
Approvals:
Smalyshev: Looks good to me, approved
jenkins-bot: Verified
diff --git a/blazegraph/pom.xml b/blazegraph/pom.xml
index 7c5017d..70626b9 100644
--- a/blazegraph/pom.xml
+++ b/blazegraph/pom.xml
@@ -40,6 +40,12 @@
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.linkeddatafragments</groupId>
+ <artifactId>ldfserver</artifactId>
+ <version>0.1.1-wmf</version>
+ <classifier>classes</classifier>
+ </dependency>
</dependencies>
<build>
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BigdataStatementToJenaStatementMapper.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BigdataStatementToJenaStatementMapper.java
new file mode 100644
index 0000000..a494245
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BigdataStatementToJenaStatementMapper.java
@@ -0,0 +1,104 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import com.hp.hpl.jena.datatypes.RDFDatatype;
+import com.hp.hpl.jena.datatypes.TypeMapper;
+import com.hp.hpl.jena.rdf.model.Property;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.rdf.model.ResourceFactory;
+import com.hp.hpl.jena.rdf.model.Statement;
+import com.hp.hpl.jena.util.iterator.Map1;
+
+import org.openrdf.model.URI;
+
+import com.bigdata.rdf.model.BigdataLiteral;
+import com.bigdata.rdf.model.BigdataResource;
+import com.bigdata.rdf.model.BigdataStatement;
+import com.bigdata.rdf.model.BigdataValue;
+
+/**
+ * Implementation of {@link Map1} that transforms {@link BigdataStatement}s to
+ * Jena {@link Statement}s.
+ *
+ * @author <a href="http://olafhartig.de">Olaf Hartig</a>
+ */
+@SuppressWarnings("all")
+public class BigdataStatementToJenaStatementMapper implements
+ Map1<BigdataStatement, Statement> {
+ /**
+ * Jenna type mapper.
+ */
+ public static final TypeMapper JENA_TYPE_MAPPER = TypeMapper.getInstance();
+
+ /**
+ * Singleton instance.
+ */
+ private static BigdataStatementToJenaStatementMapper instance;
+
+ /**
+ * Get singleton instance.
+ * @return
+ */
+ public static BigdataStatementToJenaStatementMapper getInstance() {
+ if (instance == null) {
+ instance = new BigdataStatementToJenaStatementMapper();
+ }
+ return instance;
+ }
+
+ @Override
+ public Statement map1(final BigdataStatement blzgStmt) {
+ final Resource s = convertToJenaResource(blzgStmt.getSubject());
+ final Property p = convertToJenaProperty(blzgStmt.getPredicate());
+ final RDFNode o = convertToJenaRDFNode(blzgStmt.getObject());
+
+ return ResourceFactory.createStatement(s, p, o);
+ }
+
+ /**
+ * Convert Bigdata resource to Jena resource.
+ * @param r
+ * @return Jena resource.
+ */
+ public Resource convertToJenaResource(final BigdataResource r) {
+ return ResourceFactory.createResource(r.stringValue());
+ }
+
+ /**
+ * Convert Bigdata resource to Jena property.
+ * @param r
+ * @return Jena property.
+ */
+ public Property convertToJenaProperty(final BigdataResource r) {
+ return ResourceFactory.createProperty(r.stringValue());
+ }
+
+ /**
+ * Convert Bigdata value to Jena RDF Node.
+ * @param v
+ * @return Jena RDF node.
+ */
+ public RDFNode convertToJenaRDFNode(final BigdataValue v) {
+ if (v instanceof BigdataResource)
+ return convertToJenaResource((BigdataResource) v);
+
+ if (!(v instanceof BigdataLiteral))
+ throw new IllegalArgumentException(v.getClass().getName());
+
+ final BigdataLiteral l = (BigdataLiteral) v;
+ final String lex = l.getLabel();
+ final URI datatypeURI = l.getDatatype();
+ final String languageTag = l.getLanguage();
+
+ if (datatypeURI != null) {
+ final RDFDatatype dt = JENA_TYPE_MAPPER
+ .getSafeTypeByName(datatypeURI.stringValue());
+ return ResourceFactory.createTypedLiteral(lex, dt);
+ } else if (languageTag != null) {
+ return ResourceFactory.createLangLiteral(lex, languageTag);
+ } else {
+ return ResourceFactory.createPlainLiteral(lex);
+ }
+ }
+
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPF.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPF.java
new file mode 100644
index 0000000..15fdc9e
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPF.java
@@ -0,0 +1,126 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import java.io.Closeable;
+
+import org.linkeddatafragments.fragments.tpf.TriplePatternFragmentBase;
+
+import com.bigdata.rdf.model.BigdataStatement;
+import com.bigdata.rdf.spo.ISPO;
+import com.bigdata.rdf.store.AbstractTripleStore;
+import com.bigdata.rdf.store.BigdataStatementIterator;
+import com.bigdata.relation.accesspath.IAccessPath;
+import com.hp.hpl.jena.rdf.model.Statement;
+import com.hp.hpl.jena.rdf.model.StmtIterator;
+import com.hp.hpl.jena.util.iterator.Map1Iterator;
+
+/**
+ * Implementation of
+ * {@link org.linkeddatafragments.fragments.tpf.TriplePatternFragmentBase}.
+ *
+ * @author <a href="http://olafhartig.de">Olaf Hartig</a>
+ */
+public class BlazegraphBasedTPF extends TriplePatternFragmentBase {
+ /**
+ * Statement iterator.
+ */
+ private final MyStmtIterator myStmtIt;
+
+ public BlazegraphBasedTPF(final IAccessPath<ISPO> ap,
+ final AbstractTripleStore store, final long count,
+ final long offset, final long limit, final String fragmentURL,
+ final String datasetURL, final long pageNumber) {
+ this((ap == null) // blzgStmtIt
+ ? null
+ : store.asStatementIterator(ap.iterator(offset, limit, 0)),
+ // capacity=0, i.e., default capacity will be used
+ count, // totalSize
+ fragmentURL, datasetURL, pageNumber, count < offset + limit);
// isLastPage
+ }
+
+ protected BlazegraphBasedTPF(final BigdataStatementIterator blzgStmtIt,
+ long totalSize, final String fragmentURL, final String datasetURL,
+ final long pageNumber, final boolean isLastPage) {
+ super(totalSize, fragmentURL, datasetURL, pageNumber, isLastPage);
+
+ if (blzgStmtIt != null)
+ myStmtIt = new MyStmtIterator(blzgStmtIt);
+ else
+ myStmtIt = null;
+ }
+
+ @Override
+ protected StmtIterator getNonEmptyStmtIterator() {
+ if (myStmtIt == null)
+ throw new IllegalStateException();
+
+ if (!myStmtIt.hasNext())
+ throw new IllegalStateException();
+
+ return myStmtIt;
+ }
+
+ @Override
+ public void close() {
+ myStmtIt.close();
+ }
+
+ /**
+ *
+ */
+ public static class MyStmtIterator extends Map1Iterator<BigdataStatement,
Statement>
+ implements StmtIterator, Closeable {
+ /**
+ * Blazegraph statement iterator.
+ */
+ private final BigdataStatementIterator blzgStmtIt;
+ /**
+ * Is iterator closed?
+ */
+ private boolean closed;
+
+ public MyStmtIterator(final BigdataStatementIterator blzgStmtIt) {
+ super(BigdataStatementToJenaStatementMapper.getInstance(),
+ blzgStmtIt);
+
+ this.blzgStmtIt = blzgStmtIt;
+ }
+
+ @Override
+ public Statement nextStatement() {
+ return next();
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (closed)
+ return false;
+
+ if (!blzgStmtIt.hasNext()) {
+ close();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void close() {
+ if (closed)
+ return;
+
+ blzgStmtIt.close();
+ super.close();
+ closed = true;
+ }
+
+ /**
+ * Is iterator closed?
+ * @return true or false
+ */
+ public boolean isClosed() {
+ return closed;
+ }
+
+ } // end of MyStmtIterator
+
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPFRequestProcessor.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPFRequestProcessor.java
new file mode 100644
index 0000000..ef72c61
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphBasedTPFRequestProcessor.java
@@ -0,0 +1,293 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.openrdf.model.Value;
+
+import com.bigdata.rdf.internal.IV;
+import com.bigdata.rdf.internal.impl.TermId;
+import com.bigdata.rdf.model.BigdataValue;
+import com.bigdata.rdf.spo.ISPO;
+import com.bigdata.rdf.spo.SPOFilter;
+import com.bigdata.rdf.store.AbstractTripleStore;
+import com.bigdata.relation.accesspath.IAccessPath;
+
+import
org.linkeddatafragments.datasource.AbstractRequestProcessorForTriplePatterns;
+import org.linkeddatafragments.fragments.ILinkedDataFragment;
+import org.linkeddatafragments.fragments.tpf.ITriplePatternElement;
+import org.linkeddatafragments.fragments.tpf.ITriplePatternFragment;
+import org.linkeddatafragments.fragments.tpf.ITriplePatternFragmentRequest;
+
+/**
+ * A Blazegraph-based data source.
+ *
+ * @author <a href="http://olafhartig.de">Olaf Hartig</a>
+ */
+public class BlazegraphBasedTPFRequestProcessor extends
+ AbstractRequestProcessorForTriplePatterns<BigdataValue, String,
String> {
+ /**
+ * Blazegraph data store.
+ */
+ private final AbstractTripleStore store;
+
+ public BlazegraphBasedTPFRequestProcessor(final AbstractTripleStore store)
{
+ this.store = store;
+ }
+
+ @Override
+ protected Worker getTPFSpecificWorker(
+ final ITriplePatternFragmentRequest<BigdataValue, String, String>
req)
+ throws IllegalArgumentException {
+ return new Worker(req);
+ }
+
+ /**
+ * Blazegraph worker class.
+ */
+ protected class Worker extends
+ AbstractRequestProcessorForTriplePatterns.Worker<BigdataValue,
String, String> {
+ public Worker(
+ final ITriplePatternFragmentRequest<BigdataValue, String,
String> req) {
+ super(req);
+ }
+
+ @SuppressWarnings("checkstyle:cyclomaticcomplexity")
+ @Override
+ protected ILinkedDataFragment createFragment(
+ final ITriplePatternElement<BigdataValue, String, String> s,
+ final ITriplePatternElement<BigdataValue, String, String> p,
+ final ITriplePatternElement<BigdataValue, String, String> o,
+ final long offset, final long limit) {
+ int numOfValues = 0;
+ if (!s.isVariable())
+ numOfValues++;
+ if (!p.isVariable())
+ numOfValues++;
+ if (!o.isVariable())
+ numOfValues++;
+
+ if (numOfValues > 0) {
+ final BigdataValue[] values = new BigdataValue[numOfValues];
+ int i = 0;
+ if (!s.isVariable())
+ values[i++] = s.asConstantTerm();
+ if (!p.isVariable())
+ values[i++] = p.asConstantTerm();
+ if (!o.isVariable())
+ values[i++] = o.asConstantTerm();
+
+ // Initialize the IVs of the values.
+ store.getLexiconRelation().addTerms(values, numOfValues,
true); // readOnly=true
+
+ // Check if some IVs have not been initialized. In this case
+ // the corresponding values are not used in any triple in the
+ // store. Hence, there cannot be any matching triple for the
+ // requested triple pattern and, thus, we return an empty TPF.
+ for (int j = 0; j < numOfValues; j++) {
+ @SuppressWarnings("rawtypes")
+ final IV iv = values[j].getIV();
+ if (iv == null || (iv instanceof TermId)
+ && ((TermId<?>) iv).getTermId() == 0L)
+ return createEmptyTriplePatternFragment();
+ }
+ }
+
+ final VariablesBasedFilter filter = createFilterIfNeeded(s, p, o);
+ final IAccessPath<ISPO> ap = store.getSPORelation().getAccessPath(
+ asIVorNull(s), asIVorNull(p), asIVorNull(o), null, //
c=null
+ filter);
+
+ return createTriplePatternFragment(ap, offset, limit);
+ }
+
+ /**
+ * Create filter based on triple request.
+ * @param s
+ * @param p
+ * @param o
+ * @return
+ */
+ @SuppressWarnings({"checkstyle:npathcomplexity",
"checkstyle:cyclomaticcomplexity"})
+ public VariablesBasedFilter createFilterIfNeeded(
+ final ITriplePatternElement<BigdataValue, String, String> s,
+ final ITriplePatternElement<BigdataValue, String, String> p,
+ final ITriplePatternElement<BigdataValue, String, String> o) {
+ if (!s.isSpecificVariable() && !p.isSpecificVariable()
+ && !o.isSpecificVariable())
+ return null;
+
+ final Set<String> varNames = new HashSet<String>();
+
+ if (s.isNamedVariable()) {
+ varNames.add(s.asNamedVariable());
+ }
+
+ if (p.isNamedVariable()) {
+ if (varNames.contains(p.asNamedVariable()))
+ return new VariablesBasedFilter(s, p, o);
+
+ varNames.add(p.asNamedVariable());
+ }
+
+ if (o.isNamedVariable() && varNames.contains(o.asNamedVariable()))
{
+ return new VariablesBasedFilter(s, p, o);
+ }
+
+ varNames.clear();
+
+ if (s.isAnonymousVariable()) {
+ varNames.add(s.asAnonymousVariable());
+ }
+
+ if (p.isAnonymousVariable()) {
+ if (varNames.contains(p.asAnonymousVariable()))
+ return new VariablesBasedFilter(s, p, o);
+
+ varNames.add(p.asAnonymousVariable());
+ }
+
+ if (o.isAnonymousVariable()
+ && varNames.contains(o.asAnonymousVariable())) {
+ return new VariablesBasedFilter(s, p, o);
+ }
+
+ return null;
+ }
+
+ /**
+ * Create the fragment.
+ * @param ap Access path
+ * @param offset Offset
+ * @param limit Limit
+ * @return
+ */
+ protected ITriplePatternFragment createTriplePatternFragment(
+ final IAccessPath<ISPO> ap, final long offset,
+ final long limit) {
+ final long count = ap.rangeCount(false); // exact=false, i.e., fast
+ // range count
+
+ if (count == 0L) {
+ return createEmptyTriplePatternFragment();
+ } else {
+ return new BlazegraphBasedTPF(ap, store, count, offset, limit,
+ request.getFragmentURL(), request.getDatasetURL(),
+ request.getPageNumber());
+ }
+ }
+
+ } // end of class Worker
+
+ /**
+ * Convert element to IV if it's constant.
+ * @param tpe
+ * @return IV or null if not constant.
+ */
+ @SuppressWarnings("rawtypes")
+ public static IV asIVorNull(
+ final ITriplePatternElement<BigdataValue, String, String> tpe) {
+ return (tpe.isVariable()) ? null : tpe.asConstantTerm().getIV();
+ }
+
+ /**
+ * Filter based on variables.
+ */
+ public static class VariablesBasedFilter extends SPOFilter<ISPO> {
+ private static final long serialVersionUID = 6979067019748992496L;
+
+ /**
+ * Check subject.
+ */
+ private final boolean checkS;
+ /**
+ * Check predicate.
+ */
+ private final boolean checkP;
+ /**
+ * Check object.
+ */
+ private final boolean checkO;
+
+ @SuppressWarnings({"checkstyle:localvariablename",
"checkstyle:cyclomaticcomplexity"})
+ public VariablesBasedFilter(
+ final ITriplePatternElement<BigdataValue, String, String> s,
+ final ITriplePatternElement<BigdataValue, String, String> p,
+ final ITriplePatternElement<BigdataValue, String, String> o) {
+ boolean _checkS = false;
+ boolean _checkP = false;
+ boolean _checkO = false;
+
+ if (s.isNamedVariable()) {
+ final String sVarName = s.asNamedVariable();
+ if (p.isNamedVariable()
+ && p.asNamedVariable().equals(sVarName)) {
+ _checkS = true;
+ _checkP = true;
+ }
+
+ if (o.isNamedVariable()
+ && o.asNamedVariable().equals(sVarName)) {
+ _checkS = true;
+ _checkO = true;
+ }
+ }
+
+ if (s.isAnonymousVariable()) {
+ final String sVarName = s.asAnonymousVariable();
+ if (p.isAnonymousVariable()
+ && p.asAnonymousVariable().equals(sVarName)) {
+ _checkS = true;
+ _checkP = true;
+ }
+
+ if (o.isAnonymousVariable()
+ && o.asAnonymousVariable().equals(sVarName)) {
+ _checkS = true;
+ _checkO = true;
+ }
+ }
+
+ if (p.isNamedVariable() && o.isNamedVariable()
+ && p.asNamedVariable().equals(o.asNamedVariable())) {
+ _checkP = true;
+ _checkO = true;
+ }
+
+ if (p.isAnonymousVariable() && o.isAnonymousVariable() && p
+ .asAnonymousVariable().equals(o.asAnonymousVariable())) {
+ _checkP = true;
+ _checkO = true;
+ }
+
+ checkS = _checkS;
+ checkP = _checkP;
+ checkO = _checkO;
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:cyclomaticcomplexity")
+ public boolean isValid(Object obj) {
+ if (!canAccept(obj))
+ return true;
+
+ final ISPO spo = (ISPO) obj;
+ final Value s = spo.getSubject();
+ final Value p = spo.getPredicate();
+ final Value o = spo.getObject();
+
+ if (checkS && checkP && !s.equals(p))
+ return false;
+
+ if (checkS && checkO && !s.equals(o))
+ return false;
+
+ if (checkP && checkO && !p.equals(o))
+ return false;
+
+ return true;
+ }
+
+ } // end of class VariablesBasedFilter
+
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSource.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSource.java
new file mode 100644
index 0000000..c8c89ab
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSource.java
@@ -0,0 +1,47 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import com.bigdata.rdf.sail.webapp.BigdataRDFContext;
+import com.bigdata.rdf.store.AbstractTripleStore;
+
+import org.linkeddatafragments.datasource.DataSourceBase;
+import org.linkeddatafragments.datasource.IFragmentRequestProcessor;
+import org.linkeddatafragments.fragments.IFragmentRequestParser;
+
+/**
+ * A Blazegraph-based data source.
+ *
+ * @author <a href="http://olafhartig.de">Olaf Hartig</a>
+ */
+public class BlazegraphDataSource extends DataSourceBase {
+ /**
+ * Blazegraph context.
+ */
+ private final BigdataRDFContext context;
+
+ public BlazegraphDataSource(final String title, final String description,
+ final BigdataRDFContext context) {
+ super(title, description);
+ this.context = context;
+ }
+
+ /**
+ * Get store for current request.
+ *
+ * @return Triple store.
+ */
+ protected AbstractTripleStore getStore() {
+ return context.getTripleStore(context.getConfig().namespace, -1);
+ }
+
+ @Override
+ public IFragmentRequestParser getRequestParser() {
+ return new TPFRequestParserForBlazegraph(
+ getStore().getLexiconRelation());
+ }
+
+ @Override
+ public IFragmentRequestProcessor getRequestProcessor() {
+ return new BlazegraphBasedTPFRequestProcessor(getStore());
+ }
+
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSourceType.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSourceType.java
new file mode 100644
index 0000000..49bbe35
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/BlazegraphDataSourceType.java
@@ -0,0 +1,42 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import com.bigdata.rdf.sail.webapp.BigdataRDFContext;
+import com.google.gson.JsonObject;
+
+import org.linkeddatafragments.datasource.IDataSource;
+import org.linkeddatafragments.datasource.IDataSourceType;
+import org.linkeddatafragments.exceptions.DataSourceCreationException;
+
+/**
+ * The type of Blazegraph-based Triple Pattern Fragment data sources.
+ *
+ * @author <a href="http://olafhartig.de">Olaf Hartig</a>
+ */
+public class BlazegraphDataSourceType implements IDataSourceType {
+ /**
+ * Blazegraph context.
+ */
+ private static BigdataRDFContext context;
+
+ /**
+ * Set Blazegraph context.
+ *
+ * @param rdfContext
+ * The context object.
+ */
+ public static void setContext(BigdataRDFContext rdfContext) {
+ context = rdfContext;
+ }
+
+ @Override
+ public IDataSource createDataSource(final String title,
+ final String description, final JsonObject settings)
+ throws DataSourceCreationException {
+ if (context == null) {
+ throw new DataSourceCreationException(title, "Context is not
set!");
+ }
+
+ return new BlazegraphDataSource(title, description, context);
+ }
+
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/LDFServlet.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/LDFServlet.java
new file mode 100644
index 0000000..96c8720
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/LDFServlet.java
@@ -0,0 +1,44 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.linkeddatafragments.servlet.LinkedDataFragmentServlet;
+
+import com.bigdata.rdf.sail.webapp.BigdataRDFServlet;
+
+/**
+ * This class implements LDF servlet.
+ * It is based on LinkedDataFragmentServlet from
http://linkeddatafragments.org/
+ * and on https://github.com/hartig/BlazegraphBasedTPFServer/
+ */
+public class LDFServlet extends BigdataRDFServlet {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -9156574015263443551L;
+
+ /**
+ * Delegate LDF servlet.
+ * It will be doing all the work.
+ */
+ private LinkedDataFragmentServlet ldfDelegate;
+ /**
+ * Overridden to create and initialize the delegate {@link Servlet}
+ * instances.
+ */
+ @Override
+ public void init() throws ServletException {
+ super.init();
+ BlazegraphDataSourceType.setContext(getBigdataRDFContext());
+ ldfDelegate = new LinkedDataFragmentServlet();
+ ldfDelegate.init(getServletConfig());
+ }
+
+ @Override
+ protected void doGet(final HttpServletRequest req,
+ final HttpServletResponse resp) throws ServletException {
+ ldfDelegate.doGet(req, resp);
+ }
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TPFRequestParserForBlazegraph.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TPFRequestParserForBlazegraph.java
new file mode 100644
index 0000000..a931a08
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TPFRequestParserForBlazegraph.java
@@ -0,0 +1,19 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import com.bigdata.rdf.lexicon.LexiconRelation;
+import com.bigdata.rdf.model.BigdataValue;
+
+import org.linkeddatafragments.fragments.tpf.TPFRequestParser;
+
+/**
+ * An {@link TPFRequestParser} for Blazegraph-based backends.
+ *
+ * @author <a href="http://olafhartig.de">Olaf Hartig</a>
+ */
+public class TPFRequestParserForBlazegraph extends
+ TPFRequestParser<BigdataValue, String, String> {
+
+ public TPFRequestParserForBlazegraph(final LexiconRelation lexicon) {
+ super(new TriplePatternElementParserForBlazegraph(lexicon));
+ }
+}
diff --git
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TriplePatternElementParserForBlazegraph.java
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TriplePatternElementParserForBlazegraph.java
new file mode 100644
index 0000000..7b6af63
--- /dev/null
+++
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/ldf/TriplePatternElementParserForBlazegraph.java
@@ -0,0 +1,69 @@
+package org.wikidata.query.rdf.blazegraph.ldf;
+
+import com.bigdata.rdf.lexicon.LexiconRelation;
+import com.bigdata.rdf.model.BigdataURI;
+import com.bigdata.rdf.model.BigdataValue;
+import com.bigdata.rdf.model.BigdataValueFactory;
+
+import org.linkeddatafragments.util.TriplePatternElementParser;
+
+/**
+ * A {@link TriplePatternElementParser} for Blazegraph-based backends.
+ *
+ * @author <a href="http://olafhartig.de">Olaf Hartig</a>
+ */
+public class TriplePatternElementParserForBlazegraph
+ extends
+ TriplePatternElementParser<BigdataValue, String, String> {
+ /**
+ * Blazegraph value factory.
+ */
+ private final BigdataValueFactory valueFactory;
+
+ public TriplePatternElementParserForBlazegraph(final LexiconRelation lex) {
+ valueFactory = lex.getValueFactory();
+ }
+
+ @Override
+ public String createNamedVariable(final String varName) {
+ return varName;
+ }
+
+ @Override
+ public String createAnonymousVariable(final String label) {
+ return label;
+ }
+
+ @Override
+ public BigdataValue createBlankNode(final String label) {
+ return valueFactory.createBNode(label);
+ }
+
+ @Override
+ public BigdataValue createURI(final String uri) {
+ return valueFactory.createURI(uri);
+ }
+
+ @Override
+ public BigdataValue createTypedLiteral(final String label,
+ final String typeURI) {
+ final BigdataURI datatypeURI = valueFactory.createURI(typeURI);
+ return valueFactory.createLiteral(label, datatypeURI);
+ }
+
+ @Override
+ public BigdataValue createLanguageLiteral(final String label,
+ final String languageTag) {
+ return valueFactory.createLiteral(label, languageTag);
+ }
+
+ @Override
+ public BigdataValue createPlainLiteral(final String label) {
+ return valueFactory.createLiteral(label);
+ }
+
+ @Override
+ public BigdataValue handleUnparsableParameter(final String parameter) {
+ throw new IllegalArgumentException();
+ }
+}
diff --git a/dist/src/script/ldf-config.json b/dist/src/script/ldf-config.json
new file mode 100644
index 0000000..62c72ea
--- /dev/null
+++ b/dist/src/script/ldf-config.json
@@ -0,0 +1,48 @@
+{
+ "title": "Wikidata Query Service LDF server",
+ "datasourcetypes": {
+ "BlazegraphDataSource" :
"org.wikidata.query.rdf.blazegraph.ldf.BlazegraphDataSourceType"
+ },
+
+ "datasources": {
+ "ldf": {
+ "title": "Wikidata",
+ "type": "BlazegraphDataSource",
+ "description": "Blazegraph data source"
+ }
+ },
+
+ "prefixes": {
+ "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
+ "xsd": "http://www.w3.org/2001/XMLSchema#",
+ "dc": "http://purl.org/dc/terms/",
+ "foaf": "http://xmlns.com/foaf/0.1/",
+ "void": "http://rdfs.org/ns/void#",
+ "xsd": "http://www.w3.org/2001/XMLSchema#",
+ "owl": "http://www.w3.org/2002/07/owl#",
+ "skos": "http://www.w3.org/2004/02/skos/core#",
+ "schema": "http://schema.org/",
+ "cc": "http://creativecommons.org/ns#",
+ "geo": "http://www.opengis.net/ont/geosparql#",
+ "prov": "http://www.w3.org/ns/prov#",
+ "wikibase": "http://wikiba.se/ontology#",
+ "wdata": "https://www.wikidata.org/wiki/Special:EntityData/",
+ "wd": "http://www.wikidata.org/entity/",
+ "wds": "http://www.wikidata.org/entity/statement/",
+ "wdref": "http://www.wikidata.org/reference/",
+ "wdv": "http://www.wikidata.org/value/",
+ "wdt": "http://www.wikidata.org/prop/direct/",
+ "p": "http://www.wikidata.org/prop/",
+ "ps": "http://www.wikidata.org/prop/statement/",
+ "psv": "http://www.wikidata.org/prop/statement/value/",
+ "psn": "http://www.wikidata.org/prop/statement/value-normalized/",
+ "pq": "http://www.wikidata.org/prop/qualifier/",
+ "pqv": "http://www.wikidata.org/prop/qualifier/value/",
+ "pqn": "http://www.wikidata.org/prop/qualifier/value-normalized/",
+ "pr": "http://www.wikidata.org/prop/reference/",
+ "prv": "http://www.wikidata.org/prop/reference/value/",
+ "prn": "http://www.wikidata.org/prop/reference/value-normalized/",
+ "wdno": "http://www.wikidata.org/prop/novalue/"
+ }
+}
diff --git a/dist/src/script/runBlazegraph.sh b/dist/src/script/runBlazegraph.sh
index 4189eda..9d1c053 100755
--- a/dist/src/script/runBlazegraph.sh
+++ b/dist/src/script/runBlazegraph.sh
@@ -7,6 +7,9 @@
MEMORY=-Xmx8g
BLAZEGRAPH_OPTS=""
CONFIG_FILE=RWStore.properties
+DEBUG=-agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n
+# Disable this for debugging
+DEBUG=
function usage() {
echo "Usage: $0 [-h <host>] [-d <dir>] [-c <context>] [-p <port>] [-o
<blazegraph options>] [-f config.properties]"
@@ -33,7 +36,7 @@
DEFAULT_GLOBE=2
echo "Running Blazegraph from `pwd` on :$PORT/$CONTEXT"
-java -server -XX:+UseG1GC ${MEMORY}
-Dcom.bigdata.rdf.sail.webapp.ConfigParams.propertyFile=${CONFIG_FILE} \
+java -server -XX:+UseG1GC ${MEMORY} ${DEBUG}
-Dcom.bigdata.rdf.sail.webapp.ConfigParams.propertyFile=${CONFIG_FILE} \
-Dorg.eclipse.jetty.server.Request.maxFormContentSize=200000000 \
-Dcom.bigdata.rdf.sparql.ast.QueryHints.analytic=true \
-Dcom.bigdata.rdf.sparql.ast.QueryHints.analyticMaxMemoryPerQuery=1073741824 \
diff --git a/docs/ChangeLog b/docs/ChangeLog
index e926df7..551e471 100644
--- a/docs/ChangeLog
+++ b/docs/ChangeLog
@@ -1,3 +1,8 @@
+0.2.4
+-----
+Add LDF server
+Add external prefix configuration
+
0.2.3
-----
Add normalized quantity predicates
diff --git a/pom.xml b/pom.xml
index 55a428c..df1286f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -409,6 +409,18 @@
<version>1.9.5</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit-dep</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
<dependencies>
diff --git a/war/pom.xml b/war/pom.xml
index 3292866..4788c94 100644
--- a/war/pom.xml
+++ b/war/pom.xml
@@ -35,6 +35,11 @@
<artifactId>blazegraph</artifactId>
<version>${project.parent.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.linkeddatafragments</groupId>
+ <artifactId>ldfserver</artifactId>
+ <version>0.1.1-wmf</version>
+ </dependency>
</dependencies>
<build>
diff --git a/war/src/assembly/dist.xml b/war/src/assembly/dist.xml
index 50a7288..76c0c2d 100644
--- a/war/src/assembly/dist.xml
+++ b/war/src/assembly/dist.xml
@@ -11,13 +11,9 @@
<fileSets>
<fileSet>
+ <useStrictFiltering>true</useStrictFiltering>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${project.basedir}/src/config</directory>
- </fileSet>
-
- <fileSet>
- <outputDirectory>html/js</outputDirectory>
- <directory>${project.basedir}/src/js</directory>
</fileSet>
</fileSets>
@@ -30,11 +26,11 @@
</includes>
<unpackOptions>
<excludes>
- <exclude>**/workbench.js</exclude>
<exclude>**/web.xml</exclude>
</excludes>
</unpackOptions>
<useProjectArtifact>false</useProjectArtifact>
+ <useStrictFiltering>true</useStrictFiltering>
</dependencySet>
<dependencySet>
@@ -43,7 +39,33 @@
<include>${project.groupId}:*:jar</include>
</includes>
<useProjectArtifact>false</useProjectArtifact>
+ <useStrictFiltering>true</useStrictFiltering>
</dependencySet>
- </dependencySets>
+ <dependencySet>
+ <outputDirectory>WEB-INF/lib</outputDirectory>
+ <includes>
+ <include>org.linkeddatafragments:ldfserver:jar</include>
+ </includes>
+ <useProjectArtifact>false</useProjectArtifact>
+ <useStrictFiltering>true</useStrictFiltering>
+ </dependencySet>
+
+
+ <dependencySet>
+ <outputDirectory>html</outputDirectory>
+ <unpack>true</unpack>
+ <includes>
+ <include>org.linkeddatafragments:ldfserver</include>
+ </includes>
+ <unpackOptions>
+ <includes>
+ <include>assets/**</include>
+ </includes>
+ </unpackOptions>
+ <useProjectArtifact>false</useProjectArtifact>
+ <useStrictFiltering>true</useStrictFiltering>
+ </dependencySet>
+
+ </dependencySets>
</assembly>
diff --git a/war/src/config/web.xml b/war/src/config/web.xml
index 619baf1..727477b 100644
--- a/war/src/config/web.xml
+++ b/war/src/config/web.xml
@@ -133,17 +133,45 @@
<servlet-class>com.bigdata.rdf.sail.webapp.CountersServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
+ <servlet>
+ <servlet-name>LDF API</servlet-name>
+ <display-name>LDF API</display-name>
+ <description>API implementing linked data fragments.</description>
+
<servlet-class>org.wikidata.query.rdf.blazegraph.ldf.LDFServlet</servlet-class>
+ <async-supported>true</async-supported>
+ <init-param>
+ <description>Configuration file for the LDF server.</description>
+ <param-name>configFile</param-name>
+ <param-value>ldf-config.json</param-value>
+ </init-param>
+ </servlet>
+ <servlet>
+ <servlet-name>ldfassets</servlet-name>
+ <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
+ <init-param>
+ <param-name>relativeResourceBase</param-name>
+ <param-value>/html/</param-value>
+ </init-param>
+ </servlet>
<!-- Note: The HALoadBalancerServlet is deployed from override-web.xml -->
<!-- Serve anything under /html/* as a simple file. -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/html/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>ldfassets</servlet-name>
+ <url-pattern>/assets/*</url-pattern>
+ </servlet-mapping>
<!-- Mapping for the default KB namespace (as configured above). -->
<servlet-mapping>
<servlet-name>REST API</servlet-name>
<url-pattern>/sparql</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>LDF API</servlet-name>
+ <url-pattern>/ldf</url-pattern>
+ </servlet-mapping>
<!-- Mapping for access to non-default KB namespaces.
<servlet-mapping>
<servlet-name>REST API</servlet-name>
--
To view, visit https://gerrit.wikimedia.org/r/317114
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I78b4edd4d725d2b87cfead92a35b31b072f31b40
Gerrit-PatchSet: 10
Gerrit-Project: wikidata/query/rdf
Gerrit-Branch: master
Gerrit-Owner: Smalyshev <[email protected]>
Gerrit-Reviewer: Smalyshev <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits