1212package org .eclipse .rdf4j .sail .shacl .ast .constraintcomponents ;
1313
1414import java .util .List ;
15+ import java .util .Optional ;
1516import java .util .Set ;
1617
1718import org .eclipse .rdf4j .model .IRI ;
1819import org .eclipse .rdf4j .model .Literal ;
1920import org .eclipse .rdf4j .model .Model ;
2021import org .eclipse .rdf4j .model .Resource ;
22+ import org .eclipse .rdf4j .model .Value ;
2123import org .eclipse .rdf4j .model .vocabulary .SHACL ;
2224import org .eclipse .rdf4j .sail .shacl .SourceConstraintComponent ;
25+ import org .eclipse .rdf4j .sail .shacl .ValidationSettings ;
26+ import org .eclipse .rdf4j .sail .shacl .ast .SparqlFragment ;
27+ import org .eclipse .rdf4j .sail .shacl .ast .StatementMatcher ;
28+ import org .eclipse .rdf4j .sail .shacl .ast .ValidationApproach ;
29+ import org .eclipse .rdf4j .sail .shacl .ast .paths .Path ;
30+ import org .eclipse .rdf4j .sail .shacl .ast .planNodes .CheckDisjointValuesBasedOnPathAndPredicate ;
31+ import org .eclipse .rdf4j .sail .shacl .ast .planNodes .PlanNode ;
32+ import org .eclipse .rdf4j .sail .shacl .ast .planNodes .PlanNodeProvider ;
33+ import org .eclipse .rdf4j .sail .shacl .ast .planNodes .UnionNode ;
34+ import org .eclipse .rdf4j .sail .shacl .ast .planNodes .Unique ;
35+ import org .eclipse .rdf4j .sail .shacl .ast .planNodes .UnorderedSelect ;
36+ import org .eclipse .rdf4j .sail .shacl .ast .planNodes .ValidationTuple ;
37+ import org .eclipse .rdf4j .sail .shacl .ast .targets .EffectiveTarget ;
38+ import org .eclipse .rdf4j .sail .shacl .ast .targets .TargetChain ;
39+ import org .eclipse .rdf4j .sail .shacl .wrapper .data .ConnectionsGroup ;
2340
2441public class DisjointConstraintComponent extends AbstractConstraintComponent {
2542
@@ -39,6 +56,89 @@ public SourceConstraintComponent getConstraintComponent() {
3956 return SourceConstraintComponent .DisjointConstraintComponent ;
4057 }
4158
59+ @ Override
60+ public PlanNode generateTransactionalValidationPlan (ConnectionsGroup connectionsGroup ,
61+ ValidationSettings validationSettings , PlanNodeProvider overrideTargetNode , Scope scope ) {
62+ StatementMatcher .StableRandomVariableProvider stableRandomVariableProvider = new StatementMatcher .StableRandomVariableProvider ();
63+
64+ TargetChain targetChain = getTargetChain ();
65+
66+ EffectiveTarget effectiveTarget = targetChain .getEffectiveTarget (scope ,
67+ connectionsGroup .getRdfsSubClassOfReasoner (), stableRandomVariableProvider );
68+ Optional <Path > path = targetChain .getPath ();
69+
70+ PlanNode allTargets ;
71+
72+ if (overrideTargetNode != null ) {
73+ allTargets = effectiveTarget .extend (overrideTargetNode .getPlanNode (), connectionsGroup ,
74+ validationSettings .getDataGraph (), scope , EffectiveTarget .Extend .right , false , null );
75+ } else {
76+
77+ PlanNode targets = effectiveTarget .getPlanNode (connectionsGroup , validationSettings .getDataGraph (),
78+ scope , true , null );
79+
80+ PlanNode allTargetsBasedOnPredicate = getAllTargetsBasedOnPredicate (connectionsGroup , validationSettings ,
81+ effectiveTarget );
82+
83+ allTargets = Unique .getInstance (UnionNode .getInstance (allTargetsBasedOnPredicate , targets ), false );
84+ }
85+
86+ StatementMatcher .Variable <Resource > subject = new StatementMatcher .Variable <>("a" );
87+ StatementMatcher .Variable <Value > object = new StatementMatcher .Variable <>("c" );
88+
89+ SparqlFragment targetQueryFragment = null ;
90+ if (path .isPresent ()) {
91+ targetQueryFragment = path .get ()
92+ .getTargetQueryFragment (subject , object , connectionsGroup .getRdfsSubClassOfReasoner (),
93+ stableRandomVariableProvider , Set .of ());
94+ }
95+
96+ return new CheckDisjointValuesBasedOnPathAndPredicate (connectionsGroup .getBaseConnection (),
97+ validationSettings .getDataGraph (), allTargets , predicate , subject , object , targetQueryFragment );
98+ }
99+
100+ private PlanNode getAllTargetsBasedOnPredicate (ConnectionsGroup connectionsGroup ,
101+ ValidationSettings validationSettings , EffectiveTarget effectiveTarget ) {
102+ PlanNode addedByPredicate = new UnorderedSelect (connectionsGroup .getAddedStatements (), null , predicate , null ,
103+ validationSettings .getDataGraph (), (s , d ) -> {
104+ return new ValidationTuple (s .getSubject (), Scope .propertyShape , false , d );
105+ });
106+
107+ PlanNode removedByPredicate = new UnorderedSelect (connectionsGroup .getRemovedStatements (), null , predicate ,
108+ null , validationSettings .getDataGraph (), (s , d ) -> {
109+ return new ValidationTuple (s .getSubject (), Scope .propertyShape , false , d );
110+ });
111+
112+ PlanNode targetFilter1 = effectiveTarget .getTargetFilter (connectionsGroup , validationSettings .getDataGraph (),
113+ addedByPredicate );
114+ PlanNode targetFilter2 = effectiveTarget .getTargetFilter (connectionsGroup , validationSettings .getDataGraph (),
115+ removedByPredicate );
116+
117+ PlanNode allTargetsBasedOnPredicate = Unique .getInstance (UnionNode .getInstance (targetFilter1 , targetFilter2 ),
118+ false );
119+ return allTargetsBasedOnPredicate ;
120+ }
121+
122+ @ Override
123+ public ValidationApproach getPreferredValidationApproach (ConnectionsGroup connectionsGroup ) {
124+ return ValidationApproach .Transactional ;
125+ }
126+
127+ @ Override
128+ public ValidationApproach getOptimalBulkValidationApproach () {
129+ return ValidationApproach .Transactional ;
130+ }
131+
132+ @ Override
133+ public boolean requiresEvaluation (ConnectionsGroup connectionsGroup , Scope scope , Resource [] dataGraph ,
134+ StatementMatcher .StableRandomVariableProvider stableRandomVariableProvider ) {
135+
136+ // todo both consider the target chain with added and removed values (path), and also added and removed values
137+ // for the predicate path
138+
139+ return true ;
140+ }
141+
42142 @ Override
43143 public ConstraintComponent deepClone () {
44144 return new DisjointConstraintComponent (predicate );
0 commit comments