aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-06-18 14:31:05 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-06-18 16:44:15 +0200
commitcd4d5aecd2c1ceedc49657f315d3a543b48779c5 (patch)
tree820b1ab5087474b7ca74cda611d33128ccf1fde7
parentrefactor: clean up Symbol constructor (diff)
downloadrefinery-cd4d5aecd2c1ceedc49657f315d3a543b48779c5.tar.gz
refinery-cd4d5aecd2c1ceedc49657f315d3a543b48779c5.tar.zst
refinery-cd4d5aecd2c1ceedc49657f315d3a543b48779c5.zip
refactor: prefer Query.of over Dnf.of
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java80
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java69
-rw-r--r--subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java57
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java10
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java2
-rw-r--r--subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java20
-rw-r--r--subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java16
-rw-r--r--subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java10
8 files changed, 118 insertions, 146 deletions
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java
index b21c254c..6aae2ebe 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java
@@ -34,7 +34,7 @@ class DiagonalQueryTest {
34 private static final AnySymbolView personView = new KeyOnlyView<>(person); 34 private static final AnySymbolView personView = new KeyOnlyView<>(person);
35 private static final AnySymbolView friendView = new KeyOnlyView<>(friend); 35 private static final AnySymbolView friendView = new KeyOnlyView<>(friend);
36 private static final AnySymbolView symbolView = new KeyOnlyView<>(symbol); 36 private static final AnySymbolView symbolView = new KeyOnlyView<>(symbol);
37 private static final AnySymbolView intSymbolView = new FunctionView<>(intSymbol); 37 private static final FunctionView<Integer> intSymbolView = new FunctionView<>(intSymbol);
38 38
39 @QueryEngineTest 39 @QueryEngineTest
40 void inputKeyNegationTest(QueryEvaluationHint hint) { 40 void inputKeyNegationTest(QueryEvaluationHint hint) {
@@ -76,20 +76,15 @@ class DiagonalQueryTest {
76 76
77 @QueryEngineTest 77 @QueryEngineTest
78 void subQueryNegationTest(QueryEvaluationHint hint) { 78 void subQueryNegationTest(QueryEvaluationHint hint) {
79 var subQuery = Dnf.of("SubQuery", builder -> { 79 var subQuery = Query.of("SubQuery", (builder, p1, p2, p3, p4) -> builder
80 var p1 = builder.parameter("p1"); 80 .clause(
81 var p2 = builder.parameter("p2"); 81 personView.call(p1),
82 var p3 = builder.parameter("p3"); 82 symbolView.call(p1, p2, p3, p4)
83 var p4 = builder.parameter("p4"); 83 )
84 builder.clause( 84 .clause(
85 personView.call(p1), 85 personView.call(p2),
86 symbolView.call(p1, p2, p3, p4) 86 symbolView.call(p1, p2, p3, p4)
87 ); 87 ));
88 builder.clause(
89 personView.call(p2),
90 symbolView.call(p1, p2, p3, p4)
91 );
92 });
93 var query = Query.of("Diagonal", (builder, p1) -> builder.clause(p2 -> List.of( 88 var query = Query.of("Diagonal", (builder, p1) -> builder.clause(p2 -> List.of(
94 personView.call(p1), 89 personView.call(p1),
95 not(subQuery.call(p1, p1, p2, p2)) 90 not(subQuery.call(p1, p1, p2, p2))
@@ -167,20 +162,14 @@ class DiagonalQueryTest {
167 162
168 @QueryEngineTest 163 @QueryEngineTest
169 void subQueryCountTest(QueryEvaluationHint hint) { 164 void subQueryCountTest(QueryEvaluationHint hint) {
170 var subQuery = Dnf.of("SubQuery", builder -> { 165 var subQuery = Query.of("SubQuery", (builder, p1, p2, p3, p4) -> builder.clause(
171 var p1 = builder.parameter("p1"); 166 personView.call(p1),
172 var p2 = builder.parameter("p2"); 167 symbolView.call(p1, p2, p3, p4)
173 var p3 = builder.parameter("p3"); 168 )
174 var p4 = builder.parameter("p4"); 169 .clause(
175 builder.clause( 170 personView.call(p2),
176 personView.call(p1), 171 symbolView.call(p1, p2, p3, p4)
177 symbolView.call(p1, p2, p3, p4) 172 ));
178 );
179 builder.clause(
180 personView.call(p2),
181 symbolView.call(p1, p2, p3, p4)
182 );
183 });
184 var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder.clause(p2 -> List.of( 173 var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder.clause(p2 -> List.of(
185 personView.call(p1), 174 personView.call(p1),
186 output.assign(subQuery.count(p1, p1, p2, p2)) 175 output.assign(subQuery.count(p1, p1, p2, p2))
@@ -220,10 +209,10 @@ class DiagonalQueryTest {
220 209
221 @QueryEngineTest 210 @QueryEngineTest
222 void inputKeyAggregationTest(QueryEvaluationHint hint) { 211 void inputKeyAggregationTest(QueryEvaluationHint hint) {
223 var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder.clause(Integer.class, 212 var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder
224 (p2, y) -> List.of( 213 .clause((p2) -> List.of(
225 personView.call(p1), 214 personView.call(p1),
226 output.assign(intSymbolView.aggregate(y, INT_SUM, p1, p1, p2, p2, y)) 215 output.assign(intSymbolView.aggregate(INT_SUM, p1, p1, p2, p2))
227 ))); 216 )));
228 217
229 var store = ModelStore.builder() 218 var store = ModelStore.builder()
@@ -278,10 +267,10 @@ class DiagonalQueryTest {
278 y.assign(x) 267 y.assign(x)
279 ); 268 );
280 }); 269 });
281 var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder.clause( 270 var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder
282 Integer.class, Integer.class, (p2, y, z) -> List.of( 271 .clause(Integer.class, Integer.class, (p2, y, z) -> List.of(
283 personView.call(p1), 272 personView.call(p1),
284 output.assign(subQuery.aggregate(y, INT_SUM, p1, p1, p2, p2, y, z)) 273 output.assign(subQuery.aggregateBy(y, INT_SUM, p1, p1, p2, p2, y, z))
285 ))); 274 )));
286 275
287 var store = ModelStore.builder() 276 var store = ModelStore.builder()
@@ -355,18 +344,15 @@ class DiagonalQueryTest {
355 344
356 @QueryEngineTest 345 @QueryEngineTest
357 void subQueryTransitiveTest(QueryEvaluationHint hint) { 346 void subQueryTransitiveTest(QueryEvaluationHint hint) {
358 var subQuery = Dnf.of("SubQuery", builder -> { 347 var subQuery = Query.of("SubQuery", (builder, p1, p2) -> builder
359 var p1 = builder.parameter("p1"); 348 .clause(
360 var p2 = builder.parameter("p2"); 349 personView.call(p1),
361 builder.clause( 350 friendView.call(p1, p2)
362 personView.call(p1), 351 )
363 friendView.call(p1, p2) 352 .clause(
364 ); 353 personView.call(p2),
365 builder.clause( 354 friendView.call(p1, p2)
366 personView.call(p2), 355 ));
367 friendView.call(p1, p2)
368 );
369 });
370 var query = Query.of("Diagonal", (builder, p1) -> builder.clause( 356 var query = Query.of("Diagonal", (builder, p1) -> builder.clause(
371 personView.call(p1), 357 personView.call(p1),
372 subQuery.callTransitive(p1, p1) 358 subQuery.callTransitive(p1, p1)
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java
index 723e9180..258127e7 100644
--- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java
+++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java
@@ -9,7 +9,6 @@ import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
9import tools.refinery.store.map.Cursor; 9import tools.refinery.store.map.Cursor;
10import tools.refinery.store.model.ModelStore; 10import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.query.ModelQueryAdapter; 11import tools.refinery.store.query.ModelQueryAdapter;
12import tools.refinery.store.query.dnf.Dnf;
13import tools.refinery.store.query.dnf.Query; 12import tools.refinery.store.query.dnf.Query;
14import tools.refinery.store.query.term.Variable; 13import tools.refinery.store.query.term.Variable;
15import tools.refinery.store.query.viatra.tests.QueryEngineTest; 14import tools.refinery.store.query.viatra.tests.QueryEngineTest;
@@ -40,7 +39,7 @@ class FunctionalQueryTest {
40 private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class); 39 private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class);
41 private static final Symbol<TruthValue> friend = Symbol.of("friend", 2, TruthValue.class, TruthValue.FALSE); 40 private static final Symbol<TruthValue> friend = Symbol.of("friend", 2, TruthValue.class, TruthValue.FALSE);
42 private static final AnySymbolView personView = new KeyOnlyView<>(person); 41 private static final AnySymbolView personView = new KeyOnlyView<>(person);
43 private static final AnySymbolView ageView = new FunctionView<>(age); 42 private static final FunctionView<Integer> ageView = new FunctionView<>(age);
44 private static final AnySymbolView friendMustView = new FilteredView<>(friend, "must", TruthValue::must); 43 private static final AnySymbolView friendMustView = new FilteredView<>(friend, "must", TruthValue::must);
45 44
46 @QueryEngineTest 45 @QueryEngineTest
@@ -80,17 +79,13 @@ class FunctionalQueryTest {
80 79
81 @QueryEngineTest 80 @QueryEngineTest
82 void predicateTest(QueryEvaluationHint hint) { 81 void predicateTest(QueryEvaluationHint hint) {
83 var subQuery = Dnf.of("SubQuery", builder -> { 82 var subQuery = Query.of("SubQuery", Integer.class, (builder, p1, x) -> builder.clause(
84 var p1 = builder.parameter("p1"); 83 personView.call(p1),
85 var x = builder.parameter("x", Integer.class); 84 ageView.call(p1, x)
86 builder.clause( 85 ));
87 personView.call(p1),
88 ageView.call(p1, x)
89 );
90 });
91 var query = Query.of("Predicate", Integer.class, (builder, p1, output) -> builder.clause( 86 var query = Query.of("Predicate", Integer.class, (builder, p1, output) -> builder.clause(
92 personView.call(p1), 87 personView.call(p1),
93 subQuery.call(p1, output) 88 output.assign(subQuery.call(p1))
94 )); 89 ));
95 90
96 var store = ModelStore.builder() 91 var store = ModelStore.builder()
@@ -198,15 +193,11 @@ class FunctionalQueryTest {
198 193
199 @QueryEngineTest 194 @QueryEngineTest
200 void predicateCountTest(QueryEvaluationHint hint) { 195 void predicateCountTest(QueryEvaluationHint hint) {
201 var subQuery = Dnf.of("SubQuery", builder -> { 196 var subQuery = Query.of("SubQuery", (builder, p1, p2) -> builder.clause(
202 var p1 = builder.parameter("p1");
203 var p2 = builder.parameter("p2");
204 builder.clause(
205 personView.call(p1), 197 personView.call(p1),
206 personView.call(p2), 198 personView.call(p2),
207 friendMustView.call(p1, p2) 199 friendMustView.call(p1, p2)
208 ); 200 ));
209 });
210 var query = Query.of("Count", Integer.class, (builder, p1, output) -> builder.clause( 201 var query = Query.of("Count", Integer.class, (builder, p1, output) -> builder.clause(
211 personView.call(p1), 202 personView.call(p1),
212 output.assign(subQuery.count(p1, Variable.of())) 203 output.assign(subQuery.count(p1, Variable.of()))
@@ -244,8 +235,9 @@ class FunctionalQueryTest {
244 235
245 @QueryEngineTest 236 @QueryEngineTest
246 void inputKeyAggregationTest(QueryEvaluationHint hint) { 237 void inputKeyAggregationTest(QueryEvaluationHint hint) {
247 var query = Query.of("Aggregate", Integer.class, (builder, output) -> builder.clause(Integer.class, 238 var query = Query.of("Aggregate", Integer.class, (builder, output) -> builder.clause(
248 (y) -> List.of(output.assign(ageView.aggregate(y, INT_SUM, Variable.of(), y))))); 239 output.assign(ageView.aggregate(INT_SUM, Variable.of()))
240 ));
249 241
250 var store = ModelStore.builder() 242 var store = ModelStore.builder()
251 .symbols(age) 243 .symbols(age)
@@ -268,16 +260,13 @@ class FunctionalQueryTest {
268 260
269 @QueryEngineTest 261 @QueryEngineTest
270 void predicateAggregationTest(QueryEvaluationHint hint) { 262 void predicateAggregationTest(QueryEvaluationHint hint) {
271 var subQuery = Dnf.of("SubQuery", builder -> { 263 var subQuery = Query.of("SubQuery", Integer.class, (builder, p1, x) -> builder.clause(
272 var p1 = builder.parameter("p1"); 264 personView.call(p1),
273 var x = builder.parameter("x", Integer.class); 265 ageView.call(p1, x)
274 builder.clause( 266 ));
275 personView.call(p1), 267 var query = Query.of("Aggregate", Integer.class, (builder, output) -> builder.clause(
276 ageView.call(p1, x) 268 output.assign(subQuery.aggregate(INT_SUM, Variable.of()))
277 ); 269 ));
278 });
279 var query = Query.of("Aggregate", Integer.class, (builder, output) -> builder.clause(Integer.class,
280 (y) -> List.of(output.assign(subQuery.aggregate(y, INT_SUM, Variable.of(), y)))));
281 270
282 var store = ModelStore.builder() 271 var store = ModelStore.builder()
283 .symbols(person, age) 272 .symbols(person, age)
@@ -304,18 +293,16 @@ class FunctionalQueryTest {
304 293
305 @QueryEngineTest 294 @QueryEngineTest
306 void extremeValueTest(QueryEvaluationHint hint) { 295 void extremeValueTest(QueryEvaluationHint hint) {
307 var subQuery = Dnf.of("SubQuery", builder -> { 296 var subQuery = Query.of("SubQuery", Integer.class, (builder, p1, x) -> builder.clause(
308 var p1 = builder.parameter("p1"); 297 personView.call(p1),
309 var x = builder.parameter("x", Integer.class); 298 x.assign(friendMustView.count(p1, Variable.of()))
310 builder.clause( 299 ));
311 personView.call(p1), 300 var minQuery = Query.of("Min", Integer.class, (builder, output) -> builder.clause(
312 x.assign(friendMustView.count(p1, Variable.of())) 301 output.assign(subQuery.aggregate(INT_MIN, Variable.of()))
313 ); 302 ));
314 }); 303 var maxQuery = Query.of("Max", Integer.class, (builder, output) -> builder.clause(
315 var minQuery = Query.of("Min", Integer.class, (builder, output) -> builder.clause(Integer.class, 304 output.assign(subQuery.aggregate(INT_MAX, Variable.of()))
316 (y) -> List.of(output.assign(subQuery.aggregate(y, INT_MIN, Variable.of(), y))))); 305 ));
317 var maxQuery = Query.of("Max", Integer.class, (builder, output) -> builder.clause(Integer.class,
318 (y) -> List.of(output.assign(subQuery.aggregate(y, INT_MAX, Variable.of(), y)))));
319 306
320 var store = ModelStore.builder() 307 var store = ModelStore.builder()
321 .symbols(person, friend) 308 .symbols(person, friend)
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 de0e6da1..297cdf04 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
@@ -9,7 +9,6 @@ import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
9import org.junit.jupiter.api.Test; 9import org.junit.jupiter.api.Test;
10import tools.refinery.store.model.ModelStore; 10import tools.refinery.store.model.ModelStore;
11import tools.refinery.store.query.ModelQueryAdapter; 11import tools.refinery.store.query.ModelQueryAdapter;
12import tools.refinery.store.query.dnf.Dnf;
13import tools.refinery.store.query.dnf.Query; 12import tools.refinery.store.query.dnf.Query;
14import tools.refinery.store.query.term.Variable; 13import tools.refinery.store.query.term.Variable;
15import tools.refinery.store.query.viatra.tests.QueryEngineTest; 14import tools.refinery.store.query.viatra.tests.QueryEngineTest;
@@ -271,15 +270,11 @@ class QueryTest {
271 270
272 @QueryEngineTest 271 @QueryEngineTest
273 void patternCallTest(QueryEvaluationHint hint) { 272 void patternCallTest(QueryEvaluationHint hint) {
274 var friendPredicate = Dnf.of("Friend", builder -> { 273 var friendPredicate = Query.of("Friend", (builder, p1, p2) -> builder.clause(
275 var p1 = builder.parameter("p1"); 274 personView.call(p1),
276 var p2 = builder.parameter("p2"); 275 personView.call(p2),
277 builder.clause( 276 friendMustView.call(p1, p2)
278 personView.call(p1), 277 ));
279 personView.call(p2),
280 friendMustView.call(p1, p2)
281 );
282 });
283 var predicate = Query.of("PositivePatternCall", (builder, p3, p4) -> builder.clause( 278 var predicate = Query.of("PositivePatternCall", (builder, p3, p4) -> builder.clause(
284 personView.call(p3), 279 personView.call(p3),
285 personView.call(p4), 280 personView.call(p4),
@@ -362,15 +357,11 @@ class QueryTest {
362 357
363 @QueryEngineTest 358 @QueryEngineTest
364 void negativePatternCallTest(QueryEvaluationHint hint) { 359 void negativePatternCallTest(QueryEvaluationHint hint) {
365 var friendPredicate = Dnf.of("Friend", builder -> { 360 var friendPredicate = Query.of("Friend", (builder, p1, p2) -> builder.clause(
366 var p1 = builder.parameter("p1"); 361 personView.call(p1),
367 var p2 = builder.parameter("p2"); 362 personView.call(p2),
368 builder.clause( 363 friendMustView.call(p1, p2)
369 personView.call(p1), 364 ));
370 personView.call(p2),
371 friendMustView.call(p1, p2)
372 );
373 });
374 var predicate = Query.of("NegativePatternCall", (builder, p3, p4) -> builder.clause( 365 var predicate = Query.of("NegativePatternCall", (builder, p3, p4) -> builder.clause(
375 personView.call(p3), 366 personView.call(p3),
376 personView.call(p4), 367 personView.call(p4),
@@ -451,15 +442,11 @@ class QueryTest {
451 442
452 @QueryEngineTest 443 @QueryEngineTest
453 void negativeWithQuantificationTest(QueryEvaluationHint hint) { 444 void negativeWithQuantificationTest(QueryEvaluationHint hint) {
454 var called = Dnf.of("Called", builder -> { 445 var called = Query.of("Called", (builder, p1, p2) -> builder.clause(
455 var p1 = builder.parameter("p1"); 446 personView.call(p1),
456 var p2 = builder.parameter("p2"); 447 personView.call(p2),
457 builder.clause( 448 friendMustView.call(p1, p2)
458 personView.call(p1), 449 ));
459 personView.call(p2),
460 friendMustView.call(p1, p2)
461 );
462 });
463 var predicate = Query.of("Negative", (builder, p1) -> builder.clause( 450 var predicate = Query.of("Negative", (builder, p1) -> builder.clause(
464 personView.call(p1), 451 personView.call(p1),
465 not(called.call(p1, Variable.of())) 452 not(called.call(p1, Variable.of()))
@@ -539,15 +526,11 @@ class QueryTest {
539 526
540 @QueryEngineTest 527 @QueryEngineTest
541 void transitivePatternCallTest(QueryEvaluationHint hint) { 528 void transitivePatternCallTest(QueryEvaluationHint hint) {
542 var called = Dnf.of("Called", builder -> { 529 var called = Query.of("Called", (builder, p1, p2) -> builder.clause(
543 var p1 = builder.parameter("p1"); 530 personView.call(p1),
544 var p2 = builder.parameter("p2"); 531 personView.call(p2),
545 builder.clause( 532 friendMustView.call(p1, p2)
546 personView.call(p1), 533 ));
547 personView.call(p2),
548 friendMustView.call(p1, p2)
549 );
550 });
551 var predicate = Query.of("Transitive", (builder, p1, p2) -> builder.clause( 534 var predicate = Query.of("Transitive", (builder, p1, p2) -> builder.clause(
552 personView.call(p1), 535 personView.call(p1),
553 personView.call(p2), 536 personView.call(p2),
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java
index c0995e53..916fb35c 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java
@@ -60,13 +60,13 @@ public interface Constraint {
60 return count(List.of(arguments)); 60 return count(List.of(arguments));
61 } 61 }
62 62
63 default <R, T> AssignedValue<R> aggregate(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, 63 default <R, T> AssignedValue<R> aggregateBy(DataVariable<T> inputVariable, Aggregator<R, T> aggregator,
64 List<Variable> arguments) { 64 List<Variable> arguments) {
65 return targetVariable -> new AggregationLiteral<>(targetVariable, aggregator, inputVariable, this, arguments); 65 return targetVariable -> new AggregationLiteral<>(targetVariable, aggregator, inputVariable, this, arguments);
66 } 66 }
67 67
68 default <R, T> AssignedValue<R> aggregate(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, 68 default <R, T> AssignedValue<R> aggregateBy(DataVariable<T> inputVariable, Aggregator<R, T> aggregator,
69 Variable... arguments) { 69 Variable... arguments) {
70 return aggregate(inputVariable, aggregator, List.of(arguments)); 70 return aggregateBy(inputVariable, aggregator, List.of(arguments));
71 } 71 }
72} 72}
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java
index 6f253012..5a32b1ba 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java
@@ -74,7 +74,7 @@ public final class FunctionalQuery<T> extends Query<T> {
74 argumentsWithPlaceholder.addAll(arguments); 74 argumentsWithPlaceholder.addAll(arguments);
75 argumentsWithPlaceholder.add(placeholderVariable); 75 argumentsWithPlaceholder.add(placeholderVariable);
76 return getDnf() 76 return getDnf()
77 .aggregate(placeholderVariable, aggregator, argumentsWithPlaceholder) 77 .aggregateBy(placeholderVariable, aggregator, argumentsWithPlaceholder)
78 .toLiteral(targetVariable); 78 .toLiteral(targetVariable);
79 }; 79 };
80 } 80 }
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java
index 1b89e77c..74a5be07 100644
--- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java
+++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java
@@ -5,10 +5,12 @@
5 */ 5 */
6package tools.refinery.store.query.view; 6package tools.refinery.store.query.view;
7 7
8import tools.refinery.store.query.term.Parameter; 8import tools.refinery.store.query.term.*;
9import tools.refinery.store.query.term.ParameterDirection;
10import tools.refinery.store.representation.Symbol; 9import tools.refinery.store.representation.Symbol;
11 10
11import java.util.ArrayList;
12import java.util.List;
13
12public final class FunctionView<T> extends AbstractFunctionView<T> { 14public final class FunctionView<T> extends AbstractFunctionView<T> {
13 public FunctionView(Symbol<T> symbol, String name) { 15 public FunctionView(Symbol<T> symbol, String name) {
14 super(symbol, name, new Parameter(symbol.valueType(), ParameterDirection.OUT)); 16 super(symbol, name, new Parameter(symbol.valueType(), ParameterDirection.OUT));
@@ -17,4 +19,18 @@ public final class FunctionView<T> extends AbstractFunctionView<T> {
17 public FunctionView(Symbol<T> symbol) { 19 public FunctionView(Symbol<T> symbol) {
18 this(symbol, "function"); 20 this(symbol, "function");
19 } 21 }
22
23 public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, List<NodeVariable> arguments) {
24 return targetVariable -> {
25 var placeholderVariable = Variable.of(getSymbol().valueType());
26 var argumentsWithPlaceholder = new ArrayList<Variable>(arguments.size() + 1);
27 argumentsWithPlaceholder.addAll(arguments);
28 argumentsWithPlaceholder.add(placeholderVariable);
29 return aggregateBy(placeholderVariable, aggregator, argumentsWithPlaceholder).toLiteral(targetVariable);
30 };
31 }
32
33 public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, NodeVariable... arguments) {
34 return aggregate(aggregator, List.of(arguments));
35 }
20} 36}
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java
index 3608d09e..c52d26b2 100644
--- a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java
+++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java
@@ -38,7 +38,7 @@ class VariableDirectionTest {
38 private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class); 38 private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class);
39 private static final AnySymbolView personView = new KeyOnlyView<>(person); 39 private static final AnySymbolView personView = new KeyOnlyView<>(person);
40 private static final AnySymbolView friendView = new KeyOnlyView<>(friend); 40 private static final AnySymbolView friendView = new KeyOnlyView<>(friend);
41 private static final AnySymbolView ageView = new FunctionView<>(age); 41 private static final FunctionView<Integer> ageView = new FunctionView<>(age);
42 private static final NodeVariable p = Variable.of("p"); 42 private static final NodeVariable p = Variable.of("p");
43 private static final NodeVariable q = Variable.of("q"); 43 private static final NodeVariable q = Variable.of("q");
44 private static final DataVariable<Integer> x = Variable.of("x", Integer.class); 44 private static final DataVariable<Integer> x = Variable.of("x", Integer.class);
@@ -149,10 +149,10 @@ class VariableDirectionTest {
149 return Stream.of( 149 return Stream.of(
150 Arguments.of(not(friendView.call(p, q))), 150 Arguments.of(not(friendView.call(p, q))),
151 Arguments.of(y.assign(friendView.count(p, q))), 151 Arguments.of(y.assign(friendView.count(p, q))),
152 Arguments.of(y.assign(ageView.aggregate(z, INT_SUM, p, z))), 152 Arguments.of(y.assign(ageView.aggregate(INT_SUM, p))),
153 Arguments.of(not(dnfWithOutput.call(p, q))), 153 Arguments.of(not(dnfWithOutput.call(p, q))),
154 Arguments.of(y.assign(dnfWithOutput.count(p, q))), 154 Arguments.of(y.assign(dnfWithOutput.count(p, q))),
155 Arguments.of(y.assign(dnfWithOutputToAggregate.aggregate(z, INT_SUM, p, q, z))) 155 Arguments.of(y.assign(dnfWithOutputToAggregate.aggregateBy(z, INT_SUM, p, q, z)))
156 ); 156 );
157 } 157 }
158 158
@@ -192,8 +192,8 @@ class VariableDirectionTest {
192 Arguments.of(not(dnfWithInput.call(p, p))), 192 Arguments.of(not(dnfWithInput.call(p, p))),
193 Arguments.of(y.assign(dnfWithInput.count(p, q))), 193 Arguments.of(y.assign(dnfWithInput.count(p, q))),
194 Arguments.of(y.assign(dnfWithInput.count(p, p))), 194 Arguments.of(y.assign(dnfWithInput.count(p, p))),
195 Arguments.of(y.assign(dnfWithInputToAggregate.aggregate(z, INT_SUM, p, q, z))), 195 Arguments.of(y.assign(dnfWithInputToAggregate.aggregateBy(z, INT_SUM, p, q, z))),
196 Arguments.of(y.assign(dnfWithInputToAggregate.aggregate(z, INT_SUM, p, p, z))) 196 Arguments.of(y.assign(dnfWithInputToAggregate.aggregateBy(z, INT_SUM, p, p, z)))
197 ); 197 );
198 } 198 }
199 199
@@ -357,7 +357,7 @@ class VariableDirectionTest {
357 Arguments.of(dnfWithInput.call(x, q)), 357 Arguments.of(dnfWithInput.call(x, q)),
358 Arguments.of(not(dnfWithInput.call(x, q))), 358 Arguments.of(not(dnfWithInput.call(x, q))),
359 Arguments.of(y.assign(dnfWithInput.count(x, q))), 359 Arguments.of(y.assign(dnfWithInput.count(x, q))),
360 Arguments.of(y.assign(dnfWithInputToAggregate.aggregate(z, INT_SUM, x, q, z))) 360 Arguments.of(y.assign(dnfWithInputToAggregate.aggregateBy(z, INT_SUM, x, q, z)))
361 ); 361 );
362 } 362 }
363 363
@@ -415,10 +415,10 @@ class VariableDirectionTest {
415 Arguments.of(x.assign(constant(24))), 415 Arguments.of(x.assign(constant(24))),
416 Arguments.of(ageView.call(q, x)), 416 Arguments.of(ageView.call(q, x)),
417 Arguments.of(x.assign(personView.count(q))), 417 Arguments.of(x.assign(personView.count(q))),
418 Arguments.of(x.assign(ageView.aggregate(z, INT_SUM, q, z))), 418 Arguments.of(x.assign(ageView.aggregate(INT_SUM, q))),
419 Arguments.of(dnfWithDataOutput.call(x, q)), 419 Arguments.of(dnfWithDataOutput.call(x, q)),
420 Arguments.of(x.assign(dnfWithOutput.count(q))), 420 Arguments.of(x.assign(dnfWithOutput.count(q))),
421 Arguments.of(x.assign(dnfWithOutputToAggregate.aggregate(z, INT_SUM, q, z))) 421 Arguments.of(x.assign(dnfWithOutputToAggregate.aggregateBy(z, INT_SUM, q, z)))
422 ); 422 );
423 } 423 }
424 424
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java
index 5293b273..35910e08 100644
--- a/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java
+++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java
@@ -44,7 +44,7 @@ class AggregationLiteralTest {
44 44
45 @Test 45 @Test
46 void parameterDirectionTest() { 46 void parameterDirectionTest() {
47 var literal = x.assign(fakeConstraint.aggregate(y, INT_SUM, p, y)); 47 var literal = x.assign(fakeConstraint.aggregateBy(y, INT_SUM, p, y));
48 assertAll( 48 assertAll(
49 () -> assertThat(literal.getOutputVariables(), containsInAnyOrder(x)), 49 () -> assertThat(literal.getOutputVariables(), containsInAnyOrder(x)),
50 () -> assertThat(literal.getInputVariables(Set.of()), empty()), 50 () -> assertThat(literal.getInputVariables(Set.of()), empty()),
@@ -56,13 +56,13 @@ class AggregationLiteralTest {
56 56
57 @Test 57 @Test
58 void missingAggregationVariableTest() { 58 void missingAggregationVariableTest() {
59 var aggregation = fakeConstraint.aggregate(y, INT_SUM, p, z); 59 var aggregation = fakeConstraint.aggregateBy(y, INT_SUM, p, z);
60 assertThrows(IllegalArgumentException.class, () -> x.assign(aggregation)); 60 assertThrows(IllegalArgumentException.class, () -> x.assign(aggregation));
61 } 61 }
62 62
63 @Test 63 @Test
64 void circularAggregationVariableTest() { 64 void circularAggregationVariableTest() {
65 var aggregation = fakeConstraint.aggregate(x, INT_SUM, p, x); 65 var aggregation = fakeConstraint.aggregateBy(x, INT_SUM, p, x);
66 assertThrows(IllegalArgumentException.class, () -> x.assign(aggregation)); 66 assertThrows(IllegalArgumentException.class, () -> x.assign(aggregation));
67 } 67 }
68 68
@@ -71,7 +71,7 @@ class AggregationLiteralTest {
71 var builder = Dnf.builder() 71 var builder = Dnf.builder()
72 .clause( 72 .clause(
73 not(fakeConstraint.call(p, y)), 73 not(fakeConstraint.call(p, y)),
74 x.assign(fakeConstraint.aggregate(y, INT_SUM, p, y)) 74 x.assign(fakeConstraint.aggregateBy(y, INT_SUM, p, y))
75 ); 75 );
76 assertThrows(IllegalArgumentException.class, builder::build); 76 assertThrows(IllegalArgumentException.class, builder::build);
77 } 77 }
@@ -81,7 +81,7 @@ class AggregationLiteralTest {
81 var builder = Dnf.builder() 81 var builder = Dnf.builder()
82 .clause( 82 .clause(
83 y.assign(constant(27)), 83 y.assign(constant(27)),
84 x.assign(fakeConstraint.aggregate(y, INT_SUM, p, y)) 84 x.assign(fakeConstraint.aggregateBy(y, INT_SUM, p, y))
85 ); 85 );
86 assertThrows(IllegalArgumentException.class, builder::build); 86 assertThrows(IllegalArgumentException.class, builder::build);
87 } 87 }