aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-09 18:18:03 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-02-09 18:22:08 +0100
commit1f8a0c703b7c221e09333cca3208a084e0109269 (patch)
treefc9c8bf942b4a4fc6d08e667f2a602f9cecbad99
parentrefactor: Atom -> Literal naming convention (diff)
downloadrefinery-1f8a0c703b7c221e09333cca3208a084e0109269.tar.gz
refinery-1f8a0c703b7c221e09333cca3208a084e0109269.tar.zst
refinery-1f8a0c703b7c221e09333cca3208a084e0109269.zip
refactor: EDSL for DNF literals
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java117
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java3
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/Dnf.java18
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/Variable.java15
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/literal/CallPolarity.java8
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/literal/DnfCallLiteral.java23
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java12
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/literal/Literals.java11
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/literal/PolarLiteral.java5
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/literal/RelationViewLiteral.java24
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java20
11 files changed, 149 insertions, 107 deletions
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java
index 471fdfc9..6a3a62e3 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java
@@ -5,10 +5,6 @@ import tools.refinery.store.model.ModelStore;
5import tools.refinery.store.query.Dnf; 5import tools.refinery.store.query.Dnf;
6import tools.refinery.store.query.ModelQuery; 6import tools.refinery.store.query.ModelQuery;
7import tools.refinery.store.query.Variable; 7import tools.refinery.store.query.Variable;
8import tools.refinery.store.query.literal.CallPolarity;
9import tools.refinery.store.query.literal.DnfCallLiteral;
10import tools.refinery.store.query.literal.EquivalenceLiteral;
11import tools.refinery.store.query.literal.RelationViewLiteral;
12import tools.refinery.store.query.view.FilteredRelationView; 8import tools.refinery.store.query.view.FilteredRelationView;
13import tools.refinery.store.query.view.KeyOnlyRelationView; 9import tools.refinery.store.query.view.KeyOnlyRelationView;
14import tools.refinery.store.representation.Symbol; 10import tools.refinery.store.representation.Symbol;
@@ -21,6 +17,7 @@ import java.util.Set;
21import java.util.stream.Stream; 17import java.util.stream.Stream;
22 18
23import static org.junit.jupiter.api.Assertions.assertEquals; 19import static org.junit.jupiter.api.Assertions.assertEquals;
20import static tools.refinery.store.query.literal.Literals.not;
24 21
25class QueryTest { 22class QueryTest {
26 @Test 23 @Test
@@ -32,7 +29,7 @@ class QueryTest {
32 var p1 = new Variable("p1"); 29 var p1 = new Variable("p1");
33 var predicate = Dnf.builder("TypeConstraint") 30 var predicate = Dnf.builder("TypeConstraint")
34 .parameters(p1) 31 .parameters(p1)
35 .clause(new RelationViewLiteral(personView, p1)) 32 .clause(personView.call(p1))
36 .build(); 33 .build();
37 34
38 var store = ModelStore.builder() 35 var store = ModelStore.builder()
@@ -70,9 +67,9 @@ class QueryTest {
70 var predicate = Dnf.builder("RelationConstraint") 67 var predicate = Dnf.builder("RelationConstraint")
71 .parameters(p1, p2) 68 .parameters(p1, p2)
72 .clause( 69 .clause(
73 new RelationViewLiteral(personView, p1), 70 personView.call(p1),
74 new RelationViewLiteral(personView, p2), 71 personView.call(p2),
75 new RelationViewLiteral(friendMustView, p1, p2) 72 friendMustView.call(p1, p2)
76 ) 73 )
77 .build(); 74 .build();
78 75
@@ -117,10 +114,10 @@ class QueryTest {
117 var predicate = Dnf.builder("RelationConstraint") 114 var predicate = Dnf.builder("RelationConstraint")
118 .parameters(p1, p2) 115 .parameters(p1, p2)
119 .clause( 116 .clause(
120 new RelationViewLiteral(personView, p1), 117 personView.call(p1),
121 new RelationViewLiteral(personView, p2), 118 personView.call(p2),
122 new RelationViewLiteral(friendMustView, p1, p2), 119 friendMustView.call(p1, p2),
123 new RelationViewLiteral(friendMustView, p2, p1) 120 friendMustView.call(p2, p1)
124 ) 121 )
125 .build(); 122 .build();
126 123
@@ -172,9 +169,9 @@ class QueryTest {
172 var predicate = Dnf.builder("RelationConstraint") 169 var predicate = Dnf.builder("RelationConstraint")
173 .parameters(p1) 170 .parameters(p1)
174 .clause( 171 .clause(
175 new RelationViewLiteral(personView, p1), 172 personView.call(p1),
176 new RelationViewLiteral(personView, p2), 173 personView.call(p2),
177 new RelationViewLiteral(friendMustView, p1, p2) 174 friendMustView.call(p1, p2)
178 ) 175 )
179 .build(); 176 .build();
180 177
@@ -219,14 +216,14 @@ class QueryTest {
219 var predicate = Dnf.builder("Or") 216 var predicate = Dnf.builder("Or")
220 .parameters(p1, p2) 217 .parameters(p1, p2)
221 .clause( 218 .clause(
222 new RelationViewLiteral(personView, p1), 219 personView.call(p1),
223 new RelationViewLiteral(personView, p2), 220 personView.call(p2),
224 new RelationViewLiteral(friendMustView, p1, p2) 221 friendMustView.call(p1, p2)
225 ) 222 )
226 .clause( 223 .clause(
227 new RelationViewLiteral(animalView, p1), 224 animalView.call(p1),
228 new RelationViewLiteral(animalView, p2), 225 animalView.call(p2),
229 new RelationViewLiteral(friendMustView, p1, p2) 226 friendMustView.call(p1, p2)
230 ) 227 )
231 .build(); 228 .build();
232 229
@@ -269,9 +266,9 @@ class QueryTest {
269 var predicate = Dnf.builder("Equality") 266 var predicate = Dnf.builder("Equality")
270 .parameters(p1, p2) 267 .parameters(p1, p2)
271 .clause( 268 .clause(
272 new RelationViewLiteral(personView, p1), 269 personView.call(p1),
273 new RelationViewLiteral(personView, p2), 270 personView.call(p2),
274 new EquivalenceLiteral(p1, p2) 271 p1.isEquivalent(p2)
275 ) 272 )
276 .build(); 273 .build();
277 274
@@ -308,11 +305,11 @@ class QueryTest {
308 var predicate = Dnf.builder("Inequality") 305 var predicate = Dnf.builder("Inequality")
309 .parameters(p1, p2, p3) 306 .parameters(p1, p2, p3)
310 .clause( 307 .clause(
311 new RelationViewLiteral(personView, p1), 308 personView.call(p1),
312 new RelationViewLiteral(personView, p2), 309 personView.call(p2),
313 new RelationViewLiteral(friendMustView, p1, p3), 310 friendMustView.call(p1, p3),
314 new RelationViewLiteral(friendMustView, p2, p3), 311 friendMustView.call(p2, p3),
315 new EquivalenceLiteral(false, p1, p2) 312 p1.notEquivalent(p2)
316 ) 313 )
317 .build(); 314 .build();
318 315
@@ -352,9 +349,9 @@ class QueryTest {
352 var friendPredicate = Dnf.builder("RelationConstraint") 349 var friendPredicate = Dnf.builder("RelationConstraint")
353 .parameters(p1, p2) 350 .parameters(p1, p2)
354 .clause( 351 .clause(
355 new RelationViewLiteral(personView, p1), 352 personView.call(p1),
356 new RelationViewLiteral(personView, p2), 353 personView.call(p2),
357 new RelationViewLiteral(friendMustView, p1, p2) 354 friendMustView.call(p1, p2)
358 ) 355 )
359 .build(); 356 .build();
360 357
@@ -363,9 +360,9 @@ class QueryTest {
363 var predicate = Dnf.builder("PositivePatternCall") 360 var predicate = Dnf.builder("PositivePatternCall")
364 .parameters(p3, p4) 361 .parameters(p3, p4)
365 .clause( 362 .clause(
366 new RelationViewLiteral(personView, p3), 363 personView.call(p3),
367 new RelationViewLiteral(personView, p4), 364 personView.call(p4),
368 new DnfCallLiteral(friendPredicate, p3, p4) 365 friendPredicate.call(p3, p4)
369 ) 366 )
370 .build(); 367 .build();
371 368
@@ -405,9 +402,9 @@ class QueryTest {
405 var predicate = Dnf.builder("NegativePatternCall") 402 var predicate = Dnf.builder("NegativePatternCall")
406 .parameters(p1, p2) 403 .parameters(p1, p2)
407 .clause( 404 .clause(
408 new RelationViewLiteral(personView, p1), 405 personView.call(p1),
409 new RelationViewLiteral(personView, p2), 406 personView.call(p2),
410 new RelationViewLiteral(false, friendMustView, p1, p2) 407 not(friendMustView.call(p1, p2))
411 ) 408 )
412 .build(); 409 .build();
413 410
@@ -447,9 +444,9 @@ class QueryTest {
447 var friendPredicate = Dnf.builder("RelationConstraint") 444 var friendPredicate = Dnf.builder("RelationConstraint")
448 .parameters(p1, p2) 445 .parameters(p1, p2)
449 .clause( 446 .clause(
450 new RelationViewLiteral(personView, p1), 447 personView.call(p1),
451 new RelationViewLiteral(personView, p2), 448 personView.call(p2),
452 new RelationViewLiteral(friendMustView, p1, p2) 449 friendMustView.call(p1, p2)
453 ) 450 )
454 .build(); 451 .build();
455 452
@@ -458,9 +455,9 @@ class QueryTest {
458 var predicate = Dnf.builder("NegativePatternCall") 455 var predicate = Dnf.builder("NegativePatternCall")
459 .parameters(p3, p4) 456 .parameters(p3, p4)
460 .clause( 457 .clause(
461 new RelationViewLiteral(personView, p3), 458 personView.call(p3),
462 new RelationViewLiteral(personView, p4), 459 personView.call(p4),
463 new DnfCallLiteral(false, friendPredicate, p3, p4) 460 not(friendPredicate.call(p3, p4))
464 ) 461 )
465 .build(); 462 .build();
466 463
@@ -501,8 +498,8 @@ class QueryTest {
501 var predicate = Dnf.builder("Count") 498 var predicate = Dnf.builder("Count")
502 .parameters(p1) 499 .parameters(p1)
503 .clause( 500 .clause(
504 new RelationViewLiteral(personView, p1), 501 personView.call(p1),
505 new RelationViewLiteral(false, friendMustView, p1, p2) 502 not(friendMustView.call(p1, p2))
506 ) 503 )
507 .build(); 504 .build();
508 505
@@ -542,17 +539,17 @@ class QueryTest {
542 var called = Dnf.builder("Called") 539 var called = Dnf.builder("Called")
543 .parameters(p1, p2) 540 .parameters(p1, p2)
544 .clause( 541 .clause(
545 new RelationViewLiteral(personView, p1), 542 personView.call(p1),
546 new RelationViewLiteral(personView, p2), 543 personView.call(p2),
547 new RelationViewLiteral(friendMustView, p1, p2) 544 friendMustView.call(p1, p2)
548 ) 545 )
549 .build(); 546 .build();
550 547
551 var predicate = Dnf.builder("Count") 548 var predicate = Dnf.builder("Count")
552 .parameters(p1) 549 .parameters(p1)
553 .clause( 550 .clause(
554 new RelationViewLiteral(personView, p1), 551 personView.call(p1),
555 new DnfCallLiteral(false, called, p1, p2) 552 not(called.call(p1, p2))
556 ) 553 )
557 .build(); 554 .build();
558 555
@@ -591,9 +588,9 @@ class QueryTest {
591 var predicate = Dnf.builder("TransitivePatternCall") 588 var predicate = Dnf.builder("TransitivePatternCall")
592 .parameters(p1, p2) 589 .parameters(p1, p2)
593 .clause( 590 .clause(
594 new RelationViewLiteral(personView, p1), 591 personView.call(p1),
595 new RelationViewLiteral(personView, p2), 592 personView.call(p2),
596 new RelationViewLiteral(CallPolarity.TRANSITIVE, friendMustView, p1, p2) 593 friendMustView.callTransitive(p1, p2)
597 ) 594 )
598 .build(); 595 .build();
599 596
@@ -632,9 +629,9 @@ class QueryTest {
632 var friendPredicate = Dnf.builder("RelationConstraint") 629 var friendPredicate = Dnf.builder("RelationConstraint")
633 .parameters(p1, p2) 630 .parameters(p1, p2)
634 .clause( 631 .clause(
635 new RelationViewLiteral(personView, p1), 632 personView.call(p1),
636 new RelationViewLiteral(personView, p2), 633 personView.call(p2),
637 new RelationViewLiteral(friendMustView, p1, p2) 634 friendMustView.call(p1, p2)
638 ) 635 )
639 .build(); 636 .build();
640 637
@@ -643,9 +640,9 @@ class QueryTest {
643 var predicate = Dnf.builder("TransitivePatternCall") 640 var predicate = Dnf.builder("TransitivePatternCall")
644 .parameters(p3, p4) 641 .parameters(p3, p4)
645 .clause( 642 .clause(
646 new RelationViewLiteral(personView, p3), 643 personView.call(p3),
647 new RelationViewLiteral(personView, p4), 644 personView.call(p4),
648 new DnfCallLiteral(CallPolarity.TRANSITIVE, friendPredicate, p3, p4) 645 friendPredicate.callTransitive(p3, p4)
649 ) 646 )
650 .build(); 647 .build();
651 648
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java
index 99b942d2..461685b5 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java
@@ -5,7 +5,6 @@ import tools.refinery.store.model.ModelStore;
5import tools.refinery.store.query.Dnf; 5import tools.refinery.store.query.Dnf;
6import tools.refinery.store.query.ModelQuery; 6import tools.refinery.store.query.ModelQuery;
7import tools.refinery.store.query.Variable; 7import tools.refinery.store.query.Variable;
8import tools.refinery.store.query.literal.RelationViewLiteral;
9import tools.refinery.store.query.view.KeyOnlyRelationView; 8import tools.refinery.store.query.view.KeyOnlyRelationView;
10import tools.refinery.store.representation.Symbol; 9import tools.refinery.store.representation.Symbol;
11import tools.refinery.store.tuple.Tuple; 10import tools.refinery.store.tuple.Tuple;
@@ -22,7 +21,7 @@ class QueryTransactionTest {
22 var p1 = new Variable("p1"); 21 var p1 = new Variable("p1");
23 var predicate = Dnf.builder("TypeConstraint") 22 var predicate = Dnf.builder("TypeConstraint")
24 .parameters(p1) 23 .parameters(p1)
25 .clause(new RelationViewLiteral(personView, p1)) 24 .clause(personView.call(p1))
26 .build(); 25 .build();
27 26
28 var store = ModelStore.builder() 27 var store = ModelStore.builder()
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/Dnf.java b/subprojects/store/src/main/java/tools/refinery/store/query/Dnf.java
index f7b27b81..1eb9ac76 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/Dnf.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/Dnf.java
@@ -1,5 +1,7 @@
1package tools.refinery.store.query; 1package tools.refinery.store.query;
2 2
3import tools.refinery.store.query.literal.CallPolarity;
4import tools.refinery.store.query.literal.DnfCallLiteral;
3import tools.refinery.store.query.literal.Literal; 5import tools.refinery.store.query.literal.Literal;
4 6
5import java.util.*; 7import java.util.*;
@@ -72,6 +74,22 @@ public final class Dnf implements RelationLike {
72 return clauses; 74 return clauses;
73 } 75 }
74 76
77 public DnfCallLiteral call(CallPolarity polarity, List<Variable> substitution) {
78 return new DnfCallLiteral(polarity, this, substitution);
79 }
80
81 public DnfCallLiteral call(CallPolarity polarity, Variable... substitution) {
82 return call(polarity, List.of(substitution));
83 }
84
85 public DnfCallLiteral call(Variable... substitution) {
86 return call(CallPolarity.POSITIVE, substitution);
87 }
88
89 public DnfCallLiteral callTransitive(Variable left, Variable right) {
90 return call(CallPolarity.TRANSITIVE, List.of(left, right));
91 }
92
75 public static Builder builder() { 93 public static Builder builder() {
76 return builder(null); 94 return builder(null);
77 } 95 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java
index 6a6831ae..2eb87649 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/Variable.java
@@ -1,5 +1,8 @@
1package tools.refinery.store.query; 1package tools.refinery.store.query;
2 2
3import tools.refinery.store.query.literal.ConstantLiteral;
4import tools.refinery.store.query.literal.EquivalenceLiteral;
5
3import java.util.Objects; 6import java.util.Objects;
4 7
5public class Variable { 8public class Variable {
@@ -28,6 +31,18 @@ public class Variable {
28 return name != null; 31 return name != null;
29 } 32 }
30 33
34 public ConstantLiteral isConstant(int value) {
35 return new ConstantLiteral(this, value);
36 }
37
38 public EquivalenceLiteral isEquivalent(Variable other) {
39 return new EquivalenceLiteral(true, this, other);
40 }
41
42 public EquivalenceLiteral notEquivalent(Variable other) {
43 return new EquivalenceLiteral(false, this, other);
44 }
45
31 @Override 46 @Override
32 public boolean equals(Object o) { 47 public boolean equals(Object o) {
33 if (this == o) return true; 48 if (this == o) return true;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/literal/CallPolarity.java b/subprojects/store/src/main/java/tools/refinery/store/query/literal/CallPolarity.java
index ddea0221..84b4b771 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/literal/CallPolarity.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/literal/CallPolarity.java
@@ -22,7 +22,11 @@ public enum CallPolarity {
22 return transitive; 22 return transitive;
23 } 23 }
24 24
25 public static CallPolarity fromBoolean(boolean positive) { 25 public CallPolarity negate() {
26 return positive ? POSITIVE : NEGATIVE; 26 return switch (this) {
27 case POSITIVE -> NEGATIVE;
28 case NEGATIVE -> POSITIVE;
29 case TRANSITIVE -> throw new IllegalArgumentException("Transitive polarity cannot be negated");
30 };
27 } 31 }
28} 32}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/literal/DnfCallLiteral.java b/subprojects/store/src/main/java/tools/refinery/store/query/literal/DnfCallLiteral.java
index e3410c21..86149b33 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/literal/DnfCallLiteral.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/literal/DnfCallLiteral.java
@@ -5,28 +5,13 @@ import tools.refinery.store.query.Variable;
5 5
6import java.util.List; 6import java.util.List;
7 7
8public final class DnfCallLiteral extends CallLiteral<Dnf> { 8public final class DnfCallLiteral extends CallLiteral<Dnf> implements PolarLiteral<DnfCallLiteral> {
9 public DnfCallLiteral(CallPolarity polarity, Dnf target, List<Variable> substitution) { 9 public DnfCallLiteral(CallPolarity polarity, Dnf target, List<Variable> substitution) {
10 super(polarity, target, substitution); 10 super(polarity, target, substitution);
11 } 11 }
12 12
13 public DnfCallLiteral(CallPolarity polarity, Dnf target, Variable... substitution) { 13 @Override
14 this(polarity, target, List.of(substitution)); 14 public DnfCallLiteral negate() {
15 } 15 return new DnfCallLiteral(getPolarity().negate(), getTarget(), getSubstitution());
16
17 public DnfCallLiteral(boolean positive, Dnf target, List<Variable> substitution) {
18 this(CallPolarity.fromBoolean(positive), target, substitution);
19 }
20
21 public DnfCallLiteral(boolean positive, Dnf target, Variable... substitution) {
22 this(positive, target, List.of(substitution));
23 }
24
25 public DnfCallLiteral(Dnf target, List<Variable> substitution) {
26 this(CallPolarity.POSITIVE, target, substitution);
27 }
28
29 public DnfCallLiteral(Dnf target, Variable... substitution) {
30 this(target, List.of(substitution));
31 } 16 }
32} 17}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java b/subprojects/store/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java
index a1ec2c41..75afd50b 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java
@@ -4,14 +4,16 @@ import tools.refinery.store.query.Variable;
4 4
5import java.util.Set; 5import java.util.Set;
6 6
7public record EquivalenceLiteral(boolean positive, Variable left, Variable right) implements Literal { 7public record EquivalenceLiteral(boolean positive, Variable left, Variable right)
8 public EquivalenceLiteral(Variable left, Variable right) { 8 implements PolarLiteral<EquivalenceLiteral> {
9 this(true, left, right);
10 }
11
12 @Override 9 @Override
13 public void collectAllVariables(Set<Variable> variables) { 10 public void collectAllVariables(Set<Variable> variables) {
14 variables.add(left); 11 variables.add(left);
15 variables.add(right); 12 variables.add(right);
16 } 13 }
14
15 @Override
16 public EquivalenceLiteral negate() {
17 return new EquivalenceLiteral(!positive, left, right);
18 }
17} 19}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/literal/Literals.java b/subprojects/store/src/main/java/tools/refinery/store/query/literal/Literals.java
new file mode 100644
index 00000000..2c7e893f
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/literal/Literals.java
@@ -0,0 +1,11 @@
1package tools.refinery.store.query.literal;
2
3public final class Literals {
4 private Literals() {
5 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
6 }
7
8 public static <T extends PolarLiteral<T>> T not(PolarLiteral<T> literal) {
9 return literal.negate();
10 }
11}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/literal/PolarLiteral.java b/subprojects/store/src/main/java/tools/refinery/store/query/literal/PolarLiteral.java
new file mode 100644
index 00000000..32523675
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/literal/PolarLiteral.java
@@ -0,0 +1,5 @@
1package tools.refinery.store.query.literal;
2
3public interface PolarLiteral<T extends PolarLiteral<T>> extends Literal {
4 T negate();
5}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/literal/RelationViewLiteral.java b/subprojects/store/src/main/java/tools/refinery/store/query/literal/RelationViewLiteral.java
index e2106ba9..7fa99abb 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/literal/RelationViewLiteral.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/literal/RelationViewLiteral.java
@@ -5,28 +5,14 @@ import tools.refinery.store.query.view.AnyRelationView;
5 5
6import java.util.List; 6import java.util.List;
7 7
8public final class RelationViewLiteral extends CallLiteral<AnyRelationView> { 8public final class RelationViewLiteral extends CallLiteral<AnyRelationView>
9 implements PolarLiteral<RelationViewLiteral> {
9 public RelationViewLiteral(CallPolarity polarity, AnyRelationView target, List<Variable> substitution) { 10 public RelationViewLiteral(CallPolarity polarity, AnyRelationView target, List<Variable> substitution) {
10 super(polarity, target, substitution); 11 super(polarity, target, substitution);
11 } 12 }
12 13
13 public RelationViewLiteral(CallPolarity polarity, AnyRelationView target, Variable... substitution) { 14 @Override
14 this(polarity, target, List.of(substitution)); 15 public RelationViewLiteral negate() {
15 } 16 return new RelationViewLiteral(getPolarity().negate(), getTarget(), getSubstitution());
16
17 public RelationViewLiteral(boolean positive, AnyRelationView target, List<Variable> substitution) {
18 this(CallPolarity.fromBoolean(positive), target, substitution);
19 }
20
21 public RelationViewLiteral(boolean positive, AnyRelationView target, Variable... substitution) {
22 this(positive, target, List.of(substitution));
23 }
24
25 public RelationViewLiteral(AnyRelationView target, List<Variable> substitution) {
26 this(CallPolarity.POSITIVE, target, substitution);
27 }
28
29 public RelationViewLiteral(AnyRelationView target, Variable... substitution) {
30 this(target, List.of(substitution));
31 } 17 }
32} 18}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java
index bbec1e73..0bea962d 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/query/view/RelationView.java
@@ -2,9 +2,13 @@ package tools.refinery.store.query.view;
2 2
3import tools.refinery.store.map.CursorAsIterator; 3import tools.refinery.store.map.CursorAsIterator;
4import tools.refinery.store.model.Model; 4import tools.refinery.store.model.Model;
5import tools.refinery.store.query.Variable;
6import tools.refinery.store.query.literal.CallPolarity;
7import tools.refinery.store.query.literal.RelationViewLiteral;
5import tools.refinery.store.representation.Symbol; 8import tools.refinery.store.representation.Symbol;
6import tools.refinery.store.tuple.Tuple; 9import tools.refinery.store.tuple.Tuple;
7 10
11import java.util.List;
8import java.util.Objects; 12import java.util.Objects;
9import java.util.UUID; 13import java.util.UUID;
10 14
@@ -47,6 +51,22 @@ public abstract non-sealed class RelationView<T> implements AnyRelationView {
47 return (() -> new CursorAsIterator<>(model.getInterpretation(symbol).getAll(), this::forwardMap, this::filter)); 51 return (() -> new CursorAsIterator<>(model.getInterpretation(symbol).getAll(), this::forwardMap, this::filter));
48 } 52 }
49 53
54 public RelationViewLiteral call(CallPolarity polarity, List<Variable> substitution) {
55 return new RelationViewLiteral(polarity, this, substitution);
56 }
57
58 public RelationViewLiteral call(CallPolarity polarity, Variable... substitution) {
59 return call(polarity, List.of(substitution));
60 }
61
62 public RelationViewLiteral call(Variable... substitution) {
63 return call(CallPolarity.POSITIVE, substitution);
64 }
65
66 public RelationViewLiteral callTransitive(Variable left, Variable right) {
67 return call(CallPolarity.TRANSITIVE, List.of(left, right));
68 }
69
50 @Override 70 @Override
51 public boolean equals(Object o) { 71 public boolean equals(Object o) {
52 if (this == o) return true; 72 if (this == o) return true;