Skip to content
This repository has been archived by the owner on Feb 22, 2020. It is now read-only.

Commit

Permalink
Merge pull request #175 from eclipse/issues/1298_rdfs_reasoner_shacl
Browse files Browse the repository at this point in the history
eclipse-rdf4j/rdf4j#1298 rdfs reasoner for the SHACL engine
  • Loading branch information
hmottestad authored Feb 20, 2019
2 parents 11e0d51 + 9636ee8 commit 917f45d
Show file tree
Hide file tree
Showing 36 changed files with 776 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS
SailConnection addedStatements = shaclSailConnection.getAddedStatements();

if (overrideTargetNode != null) {
PlanNode bulkedEternalLeftOuter = new LoggingNode(new BulkedExternalLeftOuterJoin(overrideTargetNode, shaclSailConnection, path.getQuery("?a", "?c"), false), "");
PlanNode bulkedEternalLeftOuter = new LoggingNode(new BulkedExternalLeftOuterJoin(overrideTargetNode, shaclSailConnection, path.getQuery("?a", "?c", null), false), "");
// filter by type against addedStatements, this is an optimization for when you add the type statement in the same transaction
PlanNode addedStatementsTypeFilter = new LoggingNode(new ExternalTypeFilterNode(addedStatements, classResource, bulkedEternalLeftOuter, 1, false), "");

Expand Down Expand Up @@ -100,7 +100,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS
}

// also add anything that matches the path from the previousConnection, eg. if you add ":peter a foaf:Person", and ":peter foaf:knows :steve" is already added
PlanNode bulkedExternalLeftOuter = new LoggingNode(new BulkedExternalLeftOuterJoin(bufferedAddedByShape.getPlanNode(), shaclSailConnection, path.getQuery("?a", "?c"), true), "");
PlanNode bulkedExternalLeftOuter = new LoggingNode(new BulkedExternalLeftOuterJoin(bufferedAddedByShape.getPlanNode(), shaclSailConnection, path.getQuery("?a", "?c", null), true), "");

// only get tuples that came from the first or the leftOuterJoin or bulkedExternalLeftOuter,
// we don't care if you added ":peter a foaf:Person" and nothing else and there is nothing else in the underlying sail
Expand All @@ -116,12 +116,12 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS
if(shaclSailConnection.stats.hasRemoved()) {

// Handle when a type statement has been removed, first get all removed type statements that match the classResource for this shape
PlanNode removedTypeStatements = new LoggingNode(new Select(shaclSailConnection.getRemovedStatements(), "?a a <" + classResource + ">"), "");
PlanNode removedTypeStatements = new LoggingNode(new Select(shaclSailConnection.getRemovedStatements(), "?a a <" + classResource + ">"), "removedTypeStatements");

// Build a query to run against the base sail. eg:
// ?c foaf:knows ?a.
// ?c a foaf:Person.
String query = path.getQuery("?c", "?a") + nodeShape.getQuery("?c", "?q");
String query = path.getQuery("?c", "?a", null) + nodeShape.getQuery("?c", "?q", shaclSailConnection.getRdfsSubClassOfReasoner());

// do bulked external join for the removed class statements again the query above.
// Essentially gets data that is now invalid because of the removed type statement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public String toString() {
public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, PlanNode overrideTargetNode) {

if(overrideTargetNode != null){
PlanNode bulkedExternalLeftOuterJoin = new LoggingNode(new BulkedExternalLeftOuterJoin(overrideTargetNode, shaclSailConnection, path.getQuery("?a", "?c"), false), "");
PlanNode bulkedExternalLeftOuterJoin = new LoggingNode(new BulkedExternalLeftOuterJoin(overrideTargetNode, shaclSailConnection, path.getQuery("?a", "?c", null), false), "");
PlanNode groupByCount = new LoggingNode(new GroupByCount(bulkedExternalLeftOuterJoin), "");

DirectTupleFromFilter directTupleFromFilter = new DirectTupleFromFilter();
Expand Down Expand Up @@ -92,7 +92,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS

PlanNode unique = new LoggingNode(new Unique(trimmed), "");

PlanNode bulkedExternalLeftOuterJoin = new LoggingNode(new BulkedExternalLeftOuterJoin(unique, shaclSailConnection, path.getQuery("?a", "?c"), false), "");
PlanNode bulkedExternalLeftOuterJoin = new LoggingNode(new BulkedExternalLeftOuterJoin(unique, shaclSailConnection, path.getQuery("?a", "?c", null), false), "");

PlanNode groupByCount = new LoggingNode(new GroupByCount(bulkedExternalLeftOuterJoin), "");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public String toString() {
public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, PlanNode overrideTargetNode) {

if(overrideTargetNode != null){
PlanNode allStatements = new LoggingNode(new BulkedExternalLeftOuterJoin(overrideTargetNode, shaclSailConnection, path.getQuery("?a", "?c"), false), "");
PlanNode allStatements = new LoggingNode(new BulkedExternalLeftOuterJoin(overrideTargetNode, shaclSailConnection, path.getQuery("?a", "?c", null), false), "");
PlanNode groupBy = new LoggingNode(new GroupByCount(allStatements), "");

DirectTupleFromFilter filteredStatements = new DirectTupleFromFilter();
Expand Down Expand Up @@ -106,7 +106,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS

PlanNode planAddedForShape = new LoggingNode(nodeShape.getPlanAddedStatements(shaclSailConnection, nodeShape), "");

PlanNode select = new LoggingNode(shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), path.getQuery("?a", "?c"))), "");
PlanNode select = new LoggingNode(shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), path.getQuery("?a", "?c", null))), "");


if (nodeShape instanceof TargetClass) {
Expand All @@ -126,7 +126,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS

PlanNode trimTuple = new LoggingNode(new TrimTuple(minCountFilter, 0, 1), "");

PlanNode bulkedExternalLeftOuterJoin2 = new LoggingNode(new BulkedExternalLeftOuterJoin(trimTuple, shaclSailConnection, path.getQuery("?a", "?c"), false), "");
PlanNode bulkedExternalLeftOuterJoin2 = new LoggingNode(new BulkedExternalLeftOuterJoin(trimTuple, shaclSailConnection, path.getQuery("?a", "?c", null), false), "");

PlanNode groupBy2 = new LoggingNode(new GroupByCount(bulkedExternalLeftOuterJoin2), "");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.SHACL;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.SailConnection;
import org.eclipse.rdf4j.sail.shacl.RdfsSubClassOfReasoner;
import org.eclipse.rdf4j.sail.shacl.ShaclSail;
import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode;
Expand Down Expand Up @@ -50,13 +51,13 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS

@Override
public PlanNode getPlanAddedStatements(ShaclSailConnection shaclSailConnection, NodeShape nodeShape) {
PlanNode node = shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), getQuery("?a", "?c")));
PlanNode node = shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), getQuery("?a", "?c", null)));
return new TrimTuple(new LoggingNode(node, ""), 0, 1);
}

@Override
public PlanNode getPlanRemovedStatements(ShaclSailConnection shaclSailConnection, NodeShape nodeShape) {
PlanNode node = shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getRemovedStatements(), getQuery("?a", "?c")));
PlanNode node = shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getRemovedStatements(), getQuery("?a", "?c", null)));
return new TrimTuple(new LoggingNode(node, ""), 0, 1);
}

Expand All @@ -78,7 +79,7 @@ public boolean requiresEvaluation(SailConnection addedStatements, SailConnection
}

@Override
public String getQuery(String subjectVariable, String objectVariable) {
public String getQuery(String subjectVariable, String objectVariable, RdfsSubClassOfReasoner rdfsSubClassOfReasoner) {
return subjectVariable+" ?b "+objectVariable;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeS
.stream()
.map(shapes -> shapes.stream().map(shape ->
{
if(shaclSailConnection.stats.baseSailEmpty){
if(shaclSailConnection.stats.isBaseSailEmpty()){
return shape.getPlan(shaclSailConnection, nodeShape, false, null);
}
return shape.getPlan(shaclSailConnection, nodeShape, false, new LoggingNode(targetNodesToValidate.getPlanNode(), ""));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@ public class PathPropertyShape extends PropertyShape {

@Override
public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, PlanNode overrideTargetNode) {
return shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection, path.getQuery("?a", "?c")));
return shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection, path.getQuery("?a", "?c", null)));
}

@Override
public PlanNode getPlanAddedStatements(ShaclSailConnection shaclSailConnection, NodeShape nodeShape) {
return shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), path.getQuery("?a", "?c")));
return shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), path.getQuery("?a", "?c", null)));

}

@Override
public PlanNode getPlanRemovedStatements(ShaclSailConnection shaclSailConnection, NodeShape nodeShape) {
return shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getRemovedStatements(), path.getQuery("?a", "?c")));
return shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getRemovedStatements(), path.getQuery("?a", "?c", null)));

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

package org.eclipse.rdf4j.sail.shacl.AST;

import org.eclipse.rdf4j.sail.shacl.RdfsSubClassOfReasoner;

/**
* @author Håvard Ottestad
*/
public interface QueryGenerator {
String getQuery(String subjectVariable, String objectVariable);
String getQuery(String subjectVariable, String objectVariable, RdfsSubClassOfReasoner rdfsSubClassOfReasoner);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.SHACL;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.SailConnection;
import org.eclipse.rdf4j.sail.shacl.RdfsSubClassOfReasoner;

import java.util.Objects;
import java.util.stream.Stream;
Expand Down Expand Up @@ -51,7 +52,7 @@ public boolean requiresEvaluation(SailConnection addedStatements, SailConnection
}

@Override
public String getQuery(String subjectVariable, String objectVariable) {
public String getQuery(String subjectVariable, String objectVariable, RdfsSubClassOfReasoner rdfsSubClassOfReasoner) {

return subjectVariable+" <" + path + "> "+objectVariable+" . \n";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface FilterAttacher {

static public PlanNode getGenericSingleObjectPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, FilterAttacher filterAttacher, PathPropertyShape pathPropertyShape, PlanNode overrideTargetNode) {
if (overrideTargetNode != null) {
PlanNode bulkedExternalInnerJoin = new LoggingNode(new BulkedExternalInnerJoin(overrideTargetNode, shaclSailConnection, pathPropertyShape.path.getQuery("?a", "?c"), false), "");
PlanNode bulkedExternalInnerJoin = new LoggingNode(new BulkedExternalInnerJoin(overrideTargetNode, shaclSailConnection, pathPropertyShape.path.getQuery("?a", "?c", null), false), "");

DirectTupleFromFilter invalidValues = new DirectTupleFromFilter();
filterAttacher.attachFilter(bulkedExternalInnerJoin, null, new PushBasedLoggingNode(invalidValues));
Expand All @@ -33,7 +33,7 @@ static public PlanNode getGenericSingleObjectPlan(ShaclSailConnection shaclSailC

BufferedSplitter bufferedSplitter = new BufferedSplitter(addedByShape);

PlanNode addedByPath = new LoggingNode(shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), pathPropertyShape.path.getQuery("?a", "?c"))), "");
PlanNode addedByPath = new LoggingNode(shaclSailConnection.getCachedNodeFor(new Select(shaclSailConnection.getAddedStatements(), pathPropertyShape.path.getQuery("?a", "?c", null))), "");

// this is essentially pushing the filter down below the join
DirectTupleFromFilter invalidValuesDirectOnPath = new DirectTupleFromFilter();
Expand All @@ -45,14 +45,14 @@ static public PlanNode getGenericSingleObjectPlan(ShaclSailConnection shaclSailC

PlanNode top = new LoggingNode(new InnerJoin(bufferedSplitter.getPlanNode(), invalidValuesDirectOnPath, null, new PushBasedLoggingNode(discardedRight)), "");

if(!shaclSailConnection.stats.baseSailEmpty) {
if(!shaclSailConnection.stats.isBaseSailEmpty()) {
if (nodeShape instanceof TargetClass) {
PlanNode typeFilterPlan = new LoggingNode(((TargetClass) nodeShape).getTypeFilterPlan(shaclSailConnection, discardedRight), "");

top = new LoggingNode(new UnionNode(top, typeFilterPlan), "");
}

PlanNode bulkedExternalInnerJoin = new LoggingNode(new BulkedExternalInnerJoin(bufferedSplitter.getPlanNode(), shaclSailConnection, pathPropertyShape.path.getQuery("?a", "?c"), true), "");
PlanNode bulkedExternalInnerJoin = new LoggingNode(new BulkedExternalInnerJoin(bufferedSplitter.getPlanNode(), shaclSailConnection, pathPropertyShape.path.getQuery("?a", "?c", null), true), "");

top = new LoggingNode(new UnionNode(top, bulkedExternalInnerJoin), "");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.sail.NotifyingSailConnection;
import org.eclipse.rdf4j.sail.SailConnection;
import org.eclipse.rdf4j.sail.shacl.RdfsSubClassOfReasoner;
import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection;
import org.eclipse.rdf4j.sail.shacl.planNodes.ExternalTypeFilterNode;
import org.eclipse.rdf4j.sail.shacl.planNodes.LoggingNode;
import org.eclipse.rdf4j.sail.shacl.planNodes.PlanNode;
import org.eclipse.rdf4j.sail.shacl.planNodes.Select;
import org.eclipse.rdf4j.sail.shacl.planNodes.TrimTuple;

import java.util.Set;
import java.util.stream.Stream;

/**
Expand All @@ -45,18 +47,18 @@ public class TargetClass extends NodeShape {

@Override
public PlanNode getPlan(ShaclSailConnection shaclSailConnection, NodeShape nodeShape, boolean printPlans, PlanNode overrideTargetNode) {
return new TrimTuple(new LoggingNode(new Select(shaclSailConnection, getQuery("?a", "?c")), ""), 0, 1);
return new TrimTuple(new LoggingNode(new Select(shaclSailConnection, getQuery("?a", "?c", shaclSailConnection.getRdfsSubClassOfReasoner())), ""), 0, 1);
}

@Override
public PlanNode getPlanAddedStatements(ShaclSailConnection shaclSailConnection, NodeShape nodeShape) {
return new TrimTuple(new LoggingNode(new Select(shaclSailConnection.getAddedStatements(), getQuery("?a", "?c")), ""), 0, 1);
return new TrimTuple(new LoggingNode(new Select(shaclSailConnection.getAddedStatements(), getQuery("?a", "?c", null)), ""), 0, 1);

}

@Override
public PlanNode getPlanRemovedStatements(ShaclSailConnection shaclSailConnection, NodeShape nodeShape) {
return new Select(shaclSailConnection.getRemovedStatements(), getQuery("?a", "?c"));
return new Select(shaclSailConnection.getRemovedStatements(), getQuery("?a", "?c", null));
}

@Override
Expand All @@ -65,7 +67,18 @@ public boolean requiresEvaluation(SailConnection addedStatements, SailConnection
}

@Override
public String getQuery(String subjectVariable, String objectVariable) {
public String getQuery(String subjectVariable, String objectVariable, RdfsSubClassOfReasoner rdfsSubClassOfReasoner) {
if(rdfsSubClassOfReasoner != null ){
Set<Resource> resources = rdfsSubClassOfReasoner.backwardsChain(targetClass);
if(resources.size() > 1){
return resources
.stream()
.map(r -> "{ BIND(rdf:type as ?b1) \n BIND(<" + r + "> as "+objectVariable+") \n "+subjectVariable+" ?b1 "+objectVariable+". } \n")
.reduce((l,r)-> l+ " UNION "+r)
.get();
}
}

return "BIND(rdf:type as ?b1) \n BIND(<" + targetClass + "> as "+objectVariable+") \n "+subjectVariable+" ?b1 "+objectVariable+". \n";
}

Expand Down
Loading

0 comments on commit 917f45d

Please sign in to comment.