diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java index 0688db2316..dcd9291cba 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/NodeShape.java @@ -202,11 +202,12 @@ public SourceConstraintComponent getConstraintComponent() { @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode planNode = constraintComponents.stream() .map(c -> c.getAllTargetsPlan(connectionsGroup, dataGraph, Scope.nodeShape, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java index 5735bf9276..db324f3c02 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/PropertyShape.java @@ -255,10 +255,11 @@ constraintComponent, getSeverity(), t.getScope(), t.getContexts(), @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode planNode = constraintComponents.stream() .map(c -> c.getAllTargetsPlan(connectionsGroup, dataGraph, Scope.propertyShape, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java index 0b0f0266f6..fedfe84616 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractConstraintComponent.java @@ -103,7 +103,8 @@ public boolean requiresEvaluation(ConnectionsGroup connectionsGroup, Scope scope @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { throw new UnsupportedOperationException(); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java index 0e98dafb02..daba61bd6c 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractPairwiseConstraintComponent.java @@ -161,7 +161,8 @@ private PlanNode getAllTargetsBasedOnPredicate(ConnectionsGroup connectionsGroup @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java index 27794706e6..9682bc42ee 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AbstractSimpleConstraintComponent.java @@ -332,7 +332,8 @@ String literalToString(Literal literal) { @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java index aa6bb4f886..bfc71a8e13 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/AndConstraintComponent.java @@ -121,10 +121,11 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode planNode = and.stream() .map(c -> c.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java index 4b1173d525..935c1cf372 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClassConstraintComponent.java @@ -237,7 +237,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java index c5deca68ee..a12cc650c8 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ClosedConstraintComponent.java @@ -330,7 +330,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { EffectiveTarget effectiveTarget = getTargetChain().getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java index 15a153cfc6..e051b20057 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/ConstraintComponent.java @@ -63,7 +63,8 @@ boolean requiresEvaluation(ConnectionsGroup connectionsGroup, Scope scope, Resou SourceConstraintComponent getConstraintComponent(); PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider); + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings); SparqlFragment buildSparqlValidNodes_rsx_targetShape(Variable subject, Variable object, RdfsSubClassOfReasoner rdfsSubClassOfReasoner, Scope scope, diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java index c0d0f2840c..2839d3bcd7 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/DashHasValueInConstraintComponent.java @@ -150,7 +150,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java index 471cafc2bb..a4f3d66b11 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/HasValueConstraintComponent.java @@ -147,7 +147,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java index b4b3c74c90..f38c04ac44 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MaxCountConstraintComponent.java @@ -141,7 +141,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java index 1f16d608d9..7f4f4af9ae 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/MinCountConstraintComponent.java @@ -132,7 +132,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { return EmptyNode.getInstance(); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java index a4d4a208b2..40f793308a 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/NotConstraintComponent.java @@ -101,7 +101,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections planNodeProvider = overrideTargetNode; } else { planNodeProvider = () -> getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } PlanNode planNode = not.generateTransactionalValidationPlan( @@ -166,7 +166,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode allTargets; if (scope == Scope.propertyShape) { @@ -186,7 +187,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] } PlanNode notTargets = not.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider()); + new StatementMatcher.StableRandomVariableProvider(), validationSettings); return Unique.getInstance(UnionNode.getInstanceDedupe(connectionsGroup, allTargets, notTargets), false, connectionsGroup); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java index db9c674467..393e7cbd9a 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/OrConstraintComponent.java @@ -121,7 +121,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections } else { planNodeProvider = BufferedSplitter.getInstance( getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider), + stableRandomVariableProvider, validationSettings), false); } @@ -141,7 +141,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { PlanNode allTargets; if (scope == Scope.propertyShape) { @@ -162,7 +163,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] PlanNode planNode = or.stream() .map(or -> or.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider())) + new StatementMatcher.StableRandomVariableProvider(), validationSettings)) .distinct() .reduce((nodes, nodes2) -> UnionNode.getInstanceDedupe(connectionsGroup, nodes, nodes2)) .orElse(EmptyNode.getInstance()); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java index 870fcedde8..63b660bf6f 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMaxCountConstraintComponent.java @@ -28,11 +28,13 @@ import org.eclipse.rdf4j.sail.shacl.ast.Cache; import org.eclipse.rdf4j.sail.shacl.ast.NodeShape; import org.eclipse.rdf4j.sail.shacl.ast.PropertyShape; +import org.eclipse.rdf4j.sail.shacl.ast.ShaclParsingException; import org.eclipse.rdf4j.sail.shacl.ast.ShaclProperties; import org.eclipse.rdf4j.sail.shacl.ast.ShaclUnsupportedException; import org.eclipse.rdf4j.sail.shacl.ast.Shape; import org.eclipse.rdf4j.sail.shacl.ast.StatementMatcher; import org.eclipse.rdf4j.sail.shacl.ast.ValidationQuery; +import org.eclipse.rdf4j.sail.shacl.ast.paths.Path; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.AbstractBulkJoinPlanNode; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.BulkedExternalLeftOuterJoin; import org.eclipse.rdf4j.sail.shacl.ast.planNodes.GroupByCountFilter; @@ -121,22 +123,27 @@ public ValidationQuery generateSparqlValidationQuery(ConnectionsGroup connection public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connectionsGroup, ValidationSettings validationSettings, PlanNodeProvider overrideTargetNode, Scope scope) { - assert scope == Scope.propertyShape; + + if (scope != Scope.propertyShape) { + throw new ShaclParsingException( + "QualifiedMaxCountConstraintComponent can only be used on property shapes!"); + } StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider = new StatementMatcher.StableRandomVariableProvider(); PlanNode target; + EffectiveTarget effectiveTarget = getTargetChain().getEffectiveTarget(scope, + connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider); + if (overrideTargetNode != null) { - target = getTargetChain() - .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), - stableRandomVariableProvider) + target = effectiveTarget .extend(overrideTargetNode.getPlanNode(), connectionsGroup, validationSettings.getDataGraph(), scope, EffectiveTarget.Extend.right, false, null); } else { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } PlanNode planNode = negated(connectionsGroup, validationSettings, overrideTargetNode, scope); @@ -160,7 +167,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va if (overrideTargetNode == null) { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { target = getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), @@ -205,7 +212,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va if (overrideTargetNode == null) { allTargetsPlan = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { allTargetsPlan = getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), @@ -237,20 +244,29 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { assert scope == Scope.propertyShape; - PlanNode allTargets = getTargetChain() + EffectiveTarget effectiveTarget = getTargetChain() .getEffectiveTarget(Scope.propertyShape, connectionsGroup.getRdfsSubClassOfReasoner(), - stableRandomVariableProvider) - .getPlanNode(connectionsGroup, dataGraph, Scope.propertyShape, true, null); + stableRandomVariableProvider); - PlanNode subTargets = qualifiedValueShape.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider()); + Path path = getTargetChain().getPath().orElseThrow(); - return Unique - .getInstance(new TrimToTarget(UnionNode.getInstanceDedupe(connectionsGroup, allTargets, subTargets), - connectionsGroup), false, connectionsGroup); + PlanNode allTargets = getAllTargetsIncludingThoseAddedByPath(connectionsGroup, validationSettings, scope, + effectiveTarget, path, false); + + PlanNode subTargets = qualifiedValueShape.getAllTargetsPlan(connectionsGroup, dataGraph, scope, + new StatementMatcher.StableRandomVariableProvider(), validationSettings); + + return Unique.getInstance( + new TrimToTarget( + UnionNode.getInstanceDedupe(connectionsGroup, allTargets, subTargets), + connectionsGroup + ), + false, connectionsGroup + ); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java index 8f24100977..a3ad8f3a70 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/QualifiedMinCountConstraintComponent.java @@ -139,7 +139,7 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections false, null); } else { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } PlanNode planNode = negated(connectionsGroup, validationSettings, overrideTargetNode, scope); @@ -163,7 +163,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va if (overrideTargetNode == null) { target = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { PlanNode planNode = overrideTargetNode.getPlanNode(); if (planNode instanceof AllTargetsPlanNode) { @@ -211,7 +211,7 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va PlanNode allTargetsPlan; if (overrideTargetNode == null) { allTargetsPlan = getAllTargetsPlan(connectionsGroup, validationSettings.getDataGraph(), scope, - stableRandomVariableProvider); + stableRandomVariableProvider, validationSettings); } else { allTargetsPlan = getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), @@ -252,7 +252,8 @@ public PlanNode negated(ConnectionsGroup connectionsGroup, ValidationSettings va @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { assert scope == Scope.propertyShape; PlanNode allTargets = getTargetChain() @@ -261,7 +262,7 @@ public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] .getPlanNode(connectionsGroup, dataGraph, Scope.propertyShape, true, null); PlanNode subTargets = qualifiedValueShape.getAllTargetsPlan(connectionsGroup, dataGraph, scope, - new StatementMatcher.StableRandomVariableProvider()); + new StatementMatcher.StableRandomVariableProvider(), validationSettings); return Unique .getInstance(new TrimToTarget(UnionNode.getInstanceDedupe(connectionsGroup, allTargets, subTargets), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java index 512ae5b338..77af99c937 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/SparqlConstraintComponent.java @@ -224,7 +224,8 @@ private PlanNode getPlanNodeForOverrideTargetNode(ConnectionsGroup connectionsGr @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { return getTargetChain() .getEffectiveTarget(scope, connectionsGroup.getRdfsSubClassOfReasoner(), stableRandomVariableProvider) .getAllTargets(connectionsGroup, dataGraph, scope); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java index ac13fc1b1e..9985873151 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/UniqueLangConstraintComponent.java @@ -200,7 +200,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { if (scope == Scope.propertyShape) { PlanNode allTargetsPlan = getTargetChain() .getEffectiveTarget(Scope.nodeShape, connectionsGroup.getRdfsSubClassOfReasoner(), diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java index f2bdcc3d1e..f658cf12b4 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/constraintcomponents/VoidConstraintComponent.java @@ -59,7 +59,8 @@ public PlanNode generateTransactionalValidationPlan(ConnectionsGroup connections @Override public PlanNode getAllTargetsPlan(ConnectionsGroup connectionsGroup, Resource[] dataGraph, Scope scope, - StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider) { + StatementMatcher.StableRandomVariableProvider stableRandomVariableProvider, + ValidationSettings validationSettings) { return EmptyNode.getInstance(); } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java index ae662dce82..59af1e127e 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/paths/ZeroOrMorePath.java @@ -187,7 +187,6 @@ public SparqlFragment getTargetQueryFragment(StatementMatcher.Variable subject, new SingletonBindingSet(subjectName, statement.getSubject()), true)) { while (evaluate.hasNext()) { BindingSet next = evaluate.next(); - System.out.println(next); statements.add(new EffectiveTarget.SubjectObjectAndMatcher.SubjectObject( ((Resource) next.getValue(subject.getName())), null)); } diff --git a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java index 260fcb534e..d16ff8d6ed 100644 --- a/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java +++ b/core/sail/shacl/src/test/java/org/eclipse/rdf4j/sail/shacl/AbstractShaclTest.java @@ -111,6 +111,8 @@ abstract public class AbstractShaclTest { public static final Set SHAPE_GRAPHS = Set.of(RDF4J.SHACL_SHAPE_GRAPH, RDF4J.NIL, Values.iri("http://example.com/ns#shapesGraph1")); + public static final String INITIAL_DATA_FILE = "initialData.trig"; + private static final Set ignoredTestCases = Set.of( "test-cases/path/oneOrMorePath", "test-cases/path/zeroOrMorePath", @@ -224,7 +226,7 @@ private static Stream findTestCases(String testCase, ExpectedResult ba if (files != null) { Optional initialData = Arrays.stream(files) .map(File::getName) - .filter(name -> name.equals("initialData.trig")) + .filter(name -> name.equals(INITIAL_DATA_FILE)) .findAny(); List queries = Arrays.stream(files) .filter(f -> f.getName().endsWith(".rq")) diff --git a/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig b/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig index 54ddd788c9..7fe659e684 100644 --- a/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig +++ b/core/sail/shacl/src/test/resources/test-cases/hasValue/targetShapeAnd3/invalid/case4/initialData.trig @@ -8,4 +8,3 @@ @prefix rsx: . ex:validPerson1 ex:info "blue", "red" . - diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/query1.rq new file mode 100644 index 0000000000..b1d7c6a098 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 a ex:Person; + ex:name "en val"@en, "whatever", "other". +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/report.ttl new file mode 100644 index 0000000000..750a58a5eb --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case1/report.ttl @@ -0,0 +1,26 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:person1; + sh:resultPath ex:name; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:QualifiedMaxCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:path ex:name; + sh:qualifiedMaxCount 1; + sh:qualifiedValueShape [ a sh:NodeShape; + sh:datatype xsd:string + ] + ] + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/initialData.trig b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/initialData.trig new file mode 100644 index 0000000000..0313f7b856 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/initialData.trig @@ -0,0 +1,9 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:person1 a ex:Person ; + ex:name "en val"@en, "whatever" . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/query1.rq new file mode 100644 index 0000000000..0d73326c53 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/query1.rq @@ -0,0 +1,22 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT { + GRAPH ex:graph2 { + ex:person2 ex:change ?entity_iri . + } + ?entity_iri ex:name "NONE (string) value updated 2", "NONE (string) value updated 3". +} WHERE { + VALUES ?entity_iri { + ex:person1 + } + ?entity_iri rdf:type ?entity_iri_rdf_type__0 . + + FILTER (?entity_iri_rdf_type__0 = ex:Person) + BIND ('LangStringUniq' as ?entity_iri_ignore__1) . +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/report.ttl new file mode 100644 index 0000000000..750a58a5eb --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case2/report.ttl @@ -0,0 +1,26 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:person1; + sh:resultPath ex:name; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:QualifiedMaxCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:path ex:name; + sh:qualifiedMaxCount 1; + sh:qualifiedValueShape [ a sh:NodeShape; + sh:datatype xsd:string + ] + ] + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/initialData.trig b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/initialData.trig new file mode 100644 index 0000000000..0313f7b856 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/initialData.trig @@ -0,0 +1,9 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +ex:person1 a ex:Person ; + ex:name "en val"@en, "whatever" . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/query1.rq new file mode 100644 index 0000000000..309455e418 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 ex:name "other". +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/report.ttl new file mode 100644 index 0000000000..750a58a5eb --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/invalid/case3/report.ttl @@ -0,0 +1,26 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms false; + sh:result [ a sh:ValidationResult; + rsx:shapesGraph rdf4j:SHACLShapeGraph; + sh:focusNode ex:person1; + sh:resultPath ex:name; + sh:resultSeverity sh:Violation; + sh:sourceConstraintComponent sh:QualifiedMaxCountConstraintComponent; + sh:sourceShape [ a sh:PropertyShape; + sh:path ex:name; + sh:qualifiedMaxCount 1; + sh:qualifiedValueShape [ a sh:NodeShape; + sh:datatype xsd:string + ] + ] + ] . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/shacl.trig b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/shacl.trig new file mode 100644 index 0000000000..44c5dc4a5a --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/shacl.trig @@ -0,0 +1,17 @@ +@prefix ex: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . +@prefix rdf4j: . + +rdf4j:SHACLShapeGraph { + ex:PersonShape a sh:NodeShape; + sh:targetClass ex:Person; + sh:property [ + sh:path ex:name; + sh:qualifiedValueShape [sh:datatype xsd:string ; ] ; + sh:qualifiedMaxCount 1 ; + ] . +} diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/query1.rq new file mode 100644 index 0000000000..9009d9d2f7 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/query1.rq @@ -0,0 +1,12 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 a ex:Person; + ex:name "en val"@en, "whatever" . +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/report.ttl new file mode 100644 index 0000000000..c0518dc88b --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case1/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true . diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query1.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query1.rq new file mode 100644 index 0000000000..a77eda769f --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query1.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 ex:name "en val"@en, "whatever" . +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query2.rq b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query2.rq new file mode 100644 index 0000000000..951f75ec12 --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/query2.rq @@ -0,0 +1,11 @@ +PREFIX ex: +PREFIX owl: +PREFIX rdf: +PREFIX rdfs: +PREFIX sh: +PREFIX xsd: + +INSERT DATA { + ex:person1 a ex:Person. +} + diff --git a/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/report.ttl b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/report.ttl new file mode 100644 index 0000000000..c0518dc88b --- /dev/null +++ b/core/sail/shacl/src/test/resources/test-cases/qualifiedShape/maxCountString/valid/case2/report.ttl @@ -0,0 +1,12 @@ +@prefix ex: . +@prefix foaf: . +@prefix xsd: . +@prefix sh: . +@prefix rdf: . +@prefix rdfs: . +@prefix rsx: . +@prefix rdf4j: . + +[] a sh:ValidationReport; + rdf4j:truncated false; + sh:conforms true .