aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-21 02:18:06 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-23 13:14:24 +0200
commit7f2df1ba80aac7e1c5e99315bf5a8e32ad7456da (patch)
treed0a4c5e7104d054c6f77d1920a1459993726808c /subprojects/store-query-viatra/src/main/java/tools/refinery/store/query
parentfeat: partial interpretation for type hierarchy (diff)
downloadrefinery-7f2df1ba80aac7e1c5e99315bf5a8e32ad7456da.tar.gz
refinery-7f2df1ba80aac7e1c5e99315bf5a8e32ad7456da.tar.zst
refinery-7f2df1ba80aac7e1c5e99315bf5a8e32ad7456da.zip
feat: custom connected component RETE node
Diffstat (limited to 'subprojects/store-query-viatra/src/main/java/tools/refinery/store/query')
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java6
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java34
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RepresentativeElectionConstraint.java45
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyCopier.java35
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyNormalizer.java38
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefinerySurrogateQueryRewriter.java58
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteBackendFactory.java90
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java134
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteRecipeCompiler.java228
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryConnectionFactoryExtensions.java47
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryNodeFactoryExtensions.java44
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionAlgorithm.java137
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionNode.java120
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/StronglyConnectedComponentAlgorithm.java66
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/WeaklyConnectedComponentAlgorithm.java85
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactory.java22
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactoryImpl.java74
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackage.java41
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackageImpl.java96
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipe.java17
-rw-r--r--subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipeImpl.java105
21 files changed, 1509 insertions, 13 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
index 5ee8bd74..bf0708bf 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java
@@ -10,7 +10,6 @@ import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions;
10import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchHintOptions; 10import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchHintOptions;
11import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; 11import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
12import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; 12import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
13import org.eclipse.viatra.query.runtime.rete.matcher.ReteBackendFactory;
14import tools.refinery.store.adapter.AbstractModelAdapterBuilder; 13import tools.refinery.store.adapter.AbstractModelAdapterBuilder;
15import tools.refinery.store.model.ModelStore; 14import tools.refinery.store.model.ModelStore;
16import tools.refinery.store.query.dnf.AnyQuery; 15import tools.refinery.store.query.dnf.AnyQuery;
@@ -24,6 +23,7 @@ import tools.refinery.store.query.viatra.internal.localsearch.FlatCostFunction;
24import tools.refinery.store.query.viatra.internal.localsearch.RelationalLocalSearchBackendFactory; 23import tools.refinery.store.query.viatra.internal.localsearch.RelationalLocalSearchBackendFactory;
25import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher; 24import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher;
26import tools.refinery.store.query.viatra.internal.pquery.Dnf2PQuery; 25import tools.refinery.store.query.viatra.internal.pquery.Dnf2PQuery;
26import tools.refinery.store.query.viatra.internal.rete.RefineryReteBackendFactory;
27 27
28import java.util.*; 28import java.util.*;
29import java.util.function.Function; 29import java.util.function.Function;
@@ -41,8 +41,8 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder<Via
41 41
42 public ViatraModelQueryBuilderImpl() { 42 public ViatraModelQueryBuilderImpl() {
43 engineOptionsBuilder = new ViatraQueryEngineOptions.Builder() 43 engineOptionsBuilder = new ViatraQueryEngineOptions.Builder()
44 .withDefaultBackend(ReteBackendFactory.INSTANCE) 44 .withDefaultBackend(RefineryReteBackendFactory.INSTANCE)
45 .withDefaultCachingBackend(ReteBackendFactory.INSTANCE) 45 .withDefaultCachingBackend(RefineryReteBackendFactory.INSTANCE)
46 .withDefaultSearchBackend(RelationalLocalSearchBackendFactory.INSTANCE); 46 .withDefaultSearchBackend(RelationalLocalSearchBackendFactory.INSTANCE);
47 rewriter = new CompositeRewriter(); 47 rewriter = new CompositeRewriter();
48 rewriter.addFirst(new DuplicateDnfRemover()); 48 rewriter.addFirst(new DuplicateDnfRemover());
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java
index 15c4e0e1..af3bf32e 100644
--- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java
@@ -23,6 +23,7 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameterDirec
23import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; 23import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
24import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; 24import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
25import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; 25import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
26import tools.refinery.store.query.Constraint;
26import tools.refinery.store.query.dnf.Dnf; 27import tools.refinery.store.query.dnf.Dnf;
27import tools.refinery.store.query.dnf.DnfClause; 28import tools.refinery.store.query.dnf.DnfClause;
28import tools.refinery.store.query.dnf.SymbolicParameter; 29import tools.refinery.store.query.dnf.SymbolicParameter;
@@ -34,7 +35,10 @@ import tools.refinery.store.query.term.Variable;
34import tools.refinery.store.query.view.AnySymbolView; 35import tools.refinery.store.query.view.AnySymbolView;
35import tools.refinery.store.util.CycleDetectingMapper; 36import tools.refinery.store.util.CycleDetectingMapper;
36 37
37import java.util.*; 38import java.util.ArrayList;
39import java.util.HashMap;
40import java.util.List;
41import java.util.Map;
38import java.util.function.Function; 42import java.util.function.Function;
39 43
40public class Dnf2PQuery { 44public class Dnf2PQuery {
@@ -124,6 +128,8 @@ public class Dnf2PQuery {
124 translateCountLiteral(countLiteral, body); 128 translateCountLiteral(countLiteral, body);
125 } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) { 129 } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) {
126 translateAggregationLiteral(aggregationLiteral, body); 130 translateAggregationLiteral(aggregationLiteral, body);
131 } else if (literal instanceof RepresentativeElectionLiteral representativeElectionLiteral) {
132 translateRepresentativeElectionLiteral(representativeElectionLiteral, body);
127 } else { 133 } else {
128 throw new IllegalArgumentException("Unknown literal: " + literal.toString()); 134 throw new IllegalArgumentException("Unknown literal: " + literal.toString());
129 } 135 }
@@ -157,15 +163,7 @@ public class Dnf2PQuery {
157 } 163 }
158 case TRANSITIVE -> { 164 case TRANSITIVE -> {
159 var substitution = translateSubstitution(callLiteral.getArguments(), body); 165 var substitution = translateSubstitution(callLiteral.getArguments(), body);
160 var constraint = callLiteral.getTarget(); 166 var pattern = wrapConstraintWithIdentityArguments(callLiteral.getTarget());
161 PQuery pattern;
162 if (constraint instanceof Dnf dnf) {
163 pattern = translate(dnf);
164 } else if (constraint instanceof AnySymbolView symbolView) {
165 pattern = wrapperFactory.wrapSymbolViewIdentityArguments(symbolView);
166 } else {
167 throw new IllegalArgumentException("Unknown Constraint: " + constraint);
168 }
169 new BinaryTransitiveClosure(body, substitution, pattern); 167 new BinaryTransitiveClosure(body, substitution, pattern);
170 } 168 }
171 case NEGATIVE -> { 169 case NEGATIVE -> {
@@ -178,6 +176,16 @@ public class Dnf2PQuery {
178 } 176 }
179 } 177 }
180 178
179 private PQuery wrapConstraintWithIdentityArguments(Constraint constraint) {
180 if (constraint instanceof Dnf dnf) {
181 return translate(dnf);
182 } else if (constraint instanceof AnySymbolView symbolView) {
183 return wrapperFactory.wrapSymbolViewIdentityArguments(symbolView);
184 } else {
185 throw new IllegalArgumentException("Unknown Constraint: " + constraint);
186 }
187 }
188
181 private static Tuple translateSubstitution(List<Variable> substitution, PBody body) { 189 private static Tuple translateSubstitution(List<Variable> substitution, PBody body) {
182 int arity = substitution.size(); 190 int arity = substitution.size();
183 Object[] variables = new Object[arity]; 191 Object[] variables = new Object[arity];
@@ -240,4 +248,10 @@ public class Dnf2PQuery {
240 new AggregatorConstraint(boundAggregator, body, substitution, wrappedCall.pattern(), resultVariable, 248 new AggregatorConstraint(boundAggregator, body, substitution, wrappedCall.pattern(), resultVariable,
241 aggregatedColumn); 249 aggregatedColumn);
242 } 250 }
251
252 private void translateRepresentativeElectionLiteral(RepresentativeElectionLiteral literal, PBody body) {
253 var substitution = translateSubstitution(literal.getArguments(), body);
254 var pattern = wrapConstraintWithIdentityArguments(literal.getTarget());
255 new RepresentativeElectionConstraint(body, substitution, pattern, literal.getConnectivity());
256 }
243} 257}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RepresentativeElectionConstraint.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RepresentativeElectionConstraint.java
new file mode 100644
index 00000000..e146213e
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RepresentativeElectionConstraint.java
@@ -0,0 +1,45 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.pquery;
7
8import org.eclipse.viatra.query.runtime.matchers.context.IQueryMetaContext;
9import org.eclipse.viatra.query.runtime.matchers.psystem.*;
10import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
11import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
12import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
13import tools.refinery.store.query.literal.Connectivity;
14
15import java.util.Set;
16
17public class RepresentativeElectionConstraint extends KeyedEnumerablePConstraint<PQuery>
18 implements IQueryReference, ITypeInfoProviderConstraint {
19 private final Connectivity connectivity;
20
21 public RepresentativeElectionConstraint(PBody pBody, Tuple variablesTuple, PQuery supplierKey,
22 Connectivity connectivity) {
23 super(pBody, variablesTuple, supplierKey);
24 this.connectivity = connectivity;
25 }
26
27 public Connectivity getConnectivity() {
28 return connectivity;
29 }
30
31 @Override
32 public PQuery getReferredQuery() {
33 return supplierKey;
34 }
35
36 @Override
37 public Set<TypeJudgement> getImpliedJudgements(IQueryMetaContext context) {
38 return PositivePatternCall.getTypesImpliedByCall(supplierKey, variablesTuple);
39 }
40
41 @Override
42 protected String keyToString() {
43 return supplierKey.getFullyQualifiedName() + "#representative";
44 }
45}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyCopier.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyCopier.java
new file mode 100644
index 00000000..a833a37b
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyCopier.java
@@ -0,0 +1,35 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.pquery.rewriter;
7
8import org.eclipse.viatra.query.runtime.matchers.psystem.PBody;
9import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint;
10import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.IRewriterTraceCollector;
11import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyCopier;
12import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
13import tools.refinery.store.query.viatra.internal.pquery.RepresentativeElectionConstraint;
14
15public class RefineryPBodyCopier extends PBodyCopier {
16 public RefineryPBodyCopier(PBody body, IRewriterTraceCollector traceCollector) {
17 super(body, traceCollector);
18 }
19
20 @Override
21 protected void copyConstraint(PConstraint constraint) {
22 if (constraint instanceof RepresentativeElectionConstraint representativeElectionConstraint) {
23 copyRepresentativeElectionConstraint(representativeElectionConstraint);
24 } else {
25 super.copyConstraint(constraint);
26 }
27 }
28
29 private void copyRepresentativeElectionConstraint(RepresentativeElectionConstraint constraint) {
30 var mappedVariables = extractMappedVariables(constraint);
31 var variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables);
32 addTrace(constraint, new RepresentativeElectionConstraint(body, variablesTuple, constraint.getReferredQuery(),
33 constraint.getConnectivity()));
34 }
35}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyNormalizer.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyNormalizer.java
new file mode 100644
index 00000000..ed85a843
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefineryPBodyNormalizer.java
@@ -0,0 +1,38 @@
1/*******************************************************************************
2 * Copyright (c) 2004-2010 Gabor Bergmann and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.pquery.rewriter;
10
11import org.eclipse.viatra.query.runtime.matchers.context.IQueryMetaContext;
12import org.eclipse.viatra.query.runtime.matchers.psystem.PBody;
13import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction;
14import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
15import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyCopier;
16import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyNormalizer;
17
18import java.util.LinkedHashSet;
19import java.util.Set;
20
21public class RefineryPBodyNormalizer extends PBodyNormalizer {
22 public RefineryPBodyNormalizer(IQueryMetaContext context) {
23 super(context);
24 }
25
26 @Override
27 public PDisjunction rewrite(PDisjunction disjunction) {
28 Set<PBody> normalizedBodies = new LinkedHashSet<>();
29 for (PBody body : disjunction.getBodies()) {
30 PBodyCopier copier = new RefineryPBodyCopier(body, getTraceCollector());
31 PBody modifiedBody = copier.getCopiedBody();
32 normalizeBody(modifiedBody);
33 normalizedBodies.add(modifiedBody);
34 modifiedBody.setStatus(PQuery.PQueryStatus.OK);
35 }
36 return new PDisjunction(normalizedBodies);
37 }
38}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefinerySurrogateQueryRewriter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefinerySurrogateQueryRewriter.java
new file mode 100644
index 00000000..dc288ba0
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/rewriter/RefinerySurrogateQueryRewriter.java
@@ -0,0 +1,58 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.pquery.rewriter;
10
11import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
12import org.eclipse.viatra.query.runtime.matchers.context.surrogate.SurrogateQueryRegistry;
13import org.eclipse.viatra.query.runtime.matchers.psystem.PBody;
14import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable;
15import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
16import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
17import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction;
18import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
19import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyCopier;
20import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PDisjunctionRewriter;
21import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
22import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
23
24import java.util.LinkedHashSet;
25import java.util.Set;
26
27public class RefinerySurrogateQueryRewriter extends PDisjunctionRewriter {
28 @Override
29 public PDisjunction rewrite(PDisjunction disjunction) {
30 Set<PBody> replacedBodies = new LinkedHashSet<>();
31 for (PBody body : disjunction.getBodies()) {
32 PBodyCopier copier = new RefineryPBodyCopier(body, getTraceCollector()) {
33
34 @Override
35 protected void copyTypeConstraint(TypeConstraint typeConstraint) {
36 PVariable[] mappedVariables = extractMappedVariables(typeConstraint);
37 Tuple variablesTuple = Tuples.flatTupleOf((Object[]) mappedVariables);
38 final IInputKey supplierKey = typeConstraint.getSupplierKey();
39 if (SurrogateQueryRegistry.instance().hasSurrogateQueryFQN(supplierKey)) {
40 PQuery surrogateQuery = SurrogateQueryRegistry.instance().getSurrogateQuery(supplierKey);
41 if (surrogateQuery == null) {
42 throw new IllegalStateException("Surrogate query for feature %s not found"
43 .formatted(supplierKey.getPrettyPrintableName()));
44 }
45 addTrace(typeConstraint, new PositivePatternCall(getCopiedBody(), variablesTuple,
46 surrogateQuery));
47 } else {
48 addTrace(typeConstraint, new TypeConstraint(getCopiedBody(), variablesTuple, supplierKey));
49 }
50 }
51 };
52 PBody modifiedBody = copier.getCopiedBody();
53 replacedBodies.add(modifiedBody);
54 modifiedBody.setStatus(PQuery.PQueryStatus.OK);
55 }
56 return new PDisjunction(replacedBodies);
57 }
58}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteBackendFactory.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteBackendFactory.java
new file mode 100644
index 00000000..517e511a
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteBackendFactory.java
@@ -0,0 +1,90 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.rete;
10
11import org.eclipse.viatra.query.runtime.matchers.backend.*;
12import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
13import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
14import org.eclipse.viatra.query.runtime.rete.construction.plancompiler.ReteRecipeCompiler;
15import org.eclipse.viatra.query.runtime.rete.matcher.IncrementalMatcherCapability;
16import org.eclipse.viatra.query.runtime.rete.matcher.ReteEngine;
17import org.eclipse.viatra.query.runtime.rete.matcher.TimelyConfiguration;
18import org.eclipse.viatra.query.runtime.rete.util.Options;
19
20// Singleton implementations follows the VIATRA implementation.
21@SuppressWarnings("squid:S6548")
22public class RefineryReteBackendFactory implements IQueryBackendFactory {
23 /**
24 * EXPERIMENTAL
25 */
26 protected static final int RETE_THREADS = 0;
27
28 /**
29 * @since 2.0
30 */
31 public static final RefineryReteBackendFactory INSTANCE = new RefineryReteBackendFactory();
32
33 /**
34 * @since 1.5
35 */
36 @Override
37 public IQueryBackend create(IQueryBackendContext context) {
38 return create(context, false, null);
39 }
40
41 /**
42 * @since 2.4
43 */
44 public IQueryBackend create(IQueryBackendContext context, boolean deleteAndReDeriveEvaluation,
45 TimelyConfiguration timelyConfiguration) {
46 ReteEngine engine;
47 engine = new RefineryReteEngine(context, RETE_THREADS, deleteAndReDeriveEvaluation, timelyConfiguration);
48 IQueryBackendHintProvider hintConfiguration = engine.getHintConfiguration();
49 ReteRecipeCompiler compiler = new RefineryReteRecipeCompiler(
50 Options.builderMethod.layoutStrategy(context, hintConfiguration), context.getLogger(),
51 context.getRuntimeContext().getMetaContext(), context.getQueryCacheContext(), hintConfiguration,
52 context.getQueryAnalyzer(), deleteAndReDeriveEvaluation, timelyConfiguration);
53 engine.setCompiler(compiler);
54 return engine;
55 }
56
57 @Override
58 public Class<? extends IQueryBackend> getBackendClass() {
59 return ReteEngine.class;
60 }
61
62 @Override
63 public int hashCode() {
64 return RefineryReteBackendFactory.class.hashCode();
65 }
66
67 @Override
68 public boolean equals(Object obj) {
69 if (this == obj) {
70 return true;
71 }
72 if (obj == null) {
73 return false;
74 }
75 return obj instanceof RefineryReteBackendFactory;
76 }
77
78 /**
79 * @since 1.4
80 */
81 @Override
82 public IMatcherCapability calculateRequiredCapability(PQuery query, QueryEvaluationHint hint) {
83 return new IncrementalMatcherCapability();
84 }
85
86 @Override
87 public boolean isCaching() {
88 return true;
89 }
90}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java
new file mode 100644
index 00000000..c088219b
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteEngine.java
@@ -0,0 +1,134 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete;
7
8import org.apache.log4j.Logger;
9import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory;
10import org.eclipse.viatra.query.runtime.matchers.context.IQueryBackendContext;
11import org.eclipse.viatra.query.runtime.rete.matcher.ReteEngine;
12import org.eclipse.viatra.query.runtime.rete.matcher.TimelyConfiguration;
13import org.eclipse.viatra.query.runtime.rete.network.Network;
14import org.eclipse.viatra.query.runtime.rete.network.NodeProvisioner;
15import org.eclipse.viatra.query.runtime.rete.network.ReteContainer;
16
17import java.io.IOException;
18import java.lang.invoke.MethodHandle;
19import java.lang.invoke.MethodHandles;
20import java.lang.invoke.MethodType;
21
22public class RefineryReteEngine extends ReteEngine {
23 private static final MethodHandle REFINERY_NODE_FACTORY_CONSTRUCTOR;
24 private static final MethodHandle REFINERY_CONNECTION_FACTORY_CONSTRUCTOR;
25 private static final MethodHandle NETWORK_NODE_FACTORY_SETTER;
26 private static final MethodHandle RETE_CONTAINER_CONNECTION_FACTORY_SETTER;
27 private static final MethodHandle NODE_PROVISIONER_NODE_FACTORY_SETTER;
28 private static final MethodHandle NODE_PROVISIONER_CONNECTION_FACTORY_SETTER;
29
30 static {
31 MethodHandles.Lookup lookup;
32 try {
33 lookup = MethodHandles.privateLookupIn(Network.class, MethodHandles.lookup());
34 } catch (IllegalAccessException e) {
35 throw new IllegalStateException("Cannot create private lookup", e);
36 }
37 var refineryNodeFactoryClass = defineClassFromFile(lookup, "RefineryNodeFactory");
38 var refinaryConnectionFactoryClass = defineClassFromFile(lookup, "RefineryConnectionFactory");
39 try {
40 REFINERY_NODE_FACTORY_CONSTRUCTOR = lookup.findConstructor(refineryNodeFactoryClass,
41 MethodType.methodType(Void.TYPE, Logger.class));
42 REFINERY_CONNECTION_FACTORY_CONSTRUCTOR = lookup.findConstructor(refinaryConnectionFactoryClass,
43 MethodType.methodType(Void.TYPE, ReteContainer.class));
44 } catch (NoSuchMethodException | IllegalAccessException e) {
45 throw new IllegalStateException("Cannot get constructor", e);
46 }
47 var nodeFactoryClass = refineryNodeFactoryClass.getSuperclass();
48 var connectionFactoryClass = refinaryConnectionFactoryClass.getSuperclass();
49 try {
50 NETWORK_NODE_FACTORY_SETTER = lookup.findSetter(Network.class, "nodeFactory", nodeFactoryClass);
51 RETE_CONTAINER_CONNECTION_FACTORY_SETTER = lookup.findSetter(ReteContainer.class, "connectionFactory",
52 connectionFactoryClass);
53 NODE_PROVISIONER_NODE_FACTORY_SETTER = lookup.findSetter(NodeProvisioner.class, "nodeFactory",
54 nodeFactoryClass);
55 NODE_PROVISIONER_CONNECTION_FACTORY_SETTER = lookup.findSetter(NodeProvisioner.class, "connectionFactory",
56 connectionFactoryClass);
57 } catch (NoSuchFieldException | IllegalAccessException e) {
58 throw new IllegalStateException("Cannot get field setter", e);
59 }
60 }
61
62 private static Class<?> defineClassFromFile(MethodHandles.Lookup lookup, String name) {
63 byte[] classBytes;
64 try (var resource = Network.class.getResourceAsStream(name + ".class")) {
65 if (resource == null) {
66 throw new IllegalStateException("Cannot find %s class file".formatted(name));
67 }
68 classBytes = resource.readAllBytes();
69 } catch (IOException e) {
70 throw new IllegalStateException("Cannot read %s class file".formatted(name), e);
71 }
72 Class<?> clazz;
73 try {
74 clazz = lookup.defineClass(classBytes);
75 } catch (IllegalAccessException e) {
76 throw new IllegalStateException("Cannot define %s class".formatted(name), e);
77 }
78 return clazz;
79 }
80
81 public RefineryReteEngine(IQueryBackendContext context, int reteThreads, boolean deleteAndReDeriveEvaluation,
82 TimelyConfiguration timelyConfiguration) {
83 super(context, reteThreads, deleteAndReDeriveEvaluation, timelyConfiguration);
84 installFactories();
85 }
86
87 private void installFactories() {
88 var logger = getLogger();
89 Object nodeFactory;
90 try {
91 nodeFactory = REFINERY_NODE_FACTORY_CONSTRUCTOR.invoke(logger);
92 } catch (Error e) {
93 // Fatal JVM errors should not be wrapped.
94 throw e;
95 } catch (Throwable e) {
96 throw new IllegalStateException("Cannot construct node factory", e);
97 }
98 try {
99 NETWORK_NODE_FACTORY_SETTER.invoke(reteNet, nodeFactory);
100 } catch (Error e) {
101 // Fatal JVM errors should not be wrapped.
102 throw e;
103 } catch (Throwable e) {
104 throw new IllegalStateException("Cannot set factory", e);
105 }
106 for (var container : reteNet.getContainers()) {
107 Object connectionFactory;
108 try {
109 connectionFactory = REFINERY_CONNECTION_FACTORY_CONSTRUCTOR.invoke(container);
110 } catch (Error e) {
111 // Fatal JVM errors should not be wrapped.
112 throw e;
113 } catch (Throwable e) {
114 throw new IllegalStateException("Cannot construct connection factory", e);
115 }
116 var provisioner = container.getProvisioner();
117 try {
118 RETE_CONTAINER_CONNECTION_FACTORY_SETTER.invoke(container, connectionFactory);
119 NODE_PROVISIONER_NODE_FACTORY_SETTER.invoke(provisioner, nodeFactory);
120 NODE_PROVISIONER_CONNECTION_FACTORY_SETTER.invoke(provisioner, connectionFactory);
121 } catch (Error e) {
122 // Fatal JVM errors should not be wrapped.
123 throw e;
124 } catch (Throwable e) {
125 throw new IllegalStateException("Cannot set factory", e);
126 }
127 }
128 }
129
130 @Override
131 public IQueryBackendFactory getFactory() {
132 return RefineryReteBackendFactory.INSTANCE;
133 }
134}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteRecipeCompiler.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteRecipeCompiler.java
new file mode 100644
index 00000000..fd1b48d8
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/RefineryReteRecipeCompiler.java
@@ -0,0 +1,228 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2014, Bergmann Gabor, Istvan Rath and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.rete;
10
11import org.apache.log4j.Logger;
12import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendHintProvider;
13import org.eclipse.viatra.query.runtime.matchers.context.IQueryCacheContext;
14import org.eclipse.viatra.query.runtime.matchers.context.IQueryMetaContext;
15import org.eclipse.viatra.query.runtime.matchers.planning.IQueryPlannerStrategy;
16import org.eclipse.viatra.query.runtime.matchers.planning.SubPlan;
17import org.eclipse.viatra.query.runtime.matchers.planning.operations.PApply;
18import org.eclipse.viatra.query.runtime.matchers.planning.operations.PEnumerate;
19import org.eclipse.viatra.query.runtime.matchers.psystem.EnumerablePConstraint;
20import org.eclipse.viatra.query.runtime.matchers.psystem.analysis.QueryAnalyzer;
21import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
22import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PDisjunctionRewriterCacher;
23import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
24import org.eclipse.viatra.query.runtime.rete.construction.plancompiler.CompilerHelper;
25import org.eclipse.viatra.query.runtime.rete.construction.plancompiler.ReteRecipeCompiler;
26import org.eclipse.viatra.query.runtime.rete.matcher.TimelyConfiguration;
27import org.eclipse.viatra.query.runtime.rete.recipes.ReteNodeRecipe;
28import org.eclipse.viatra.query.runtime.rete.traceability.CompiledSubPlan;
29import org.eclipse.viatra.query.runtime.rete.traceability.PlanningTrace;
30import org.eclipse.viatra.query.runtime.rete.util.ReteHintOptions;
31import org.jetbrains.annotations.Nullable;
32import tools.refinery.store.query.viatra.internal.pquery.RepresentativeElectionConstraint;
33import tools.refinery.store.query.viatra.internal.rete.recipe.RefineryRecipesFactory;
34import tools.refinery.store.query.viatra.internal.pquery.rewriter.RefineryPBodyNormalizer;
35import tools.refinery.store.query.viatra.internal.pquery.rewriter.RefinerySurrogateQueryRewriter;
36
37import java.lang.invoke.MethodHandle;
38import java.lang.invoke.MethodHandles;
39import java.lang.invoke.MethodType;
40import java.lang.reflect.Field;
41import java.util.Map;
42
43// Since we don't modify VIATRA code, this is our last resort.
44@SuppressWarnings("squid:S3011")
45public class RefineryReteRecipeCompiler extends ReteRecipeCompiler {
46 private static final MethodHandle GET_SUB_PLAN_COMPILER_CACHE;
47 private static final MethodHandle GET_COMPILER_BACK_TRACE;
48 private static final Field NORMALIZER_FIELD;
49 private static final MethodHandle DO_COMPILE_DISPATCH;
50 private static final MethodHandle COMPILE_TO_NATURAL_JOIN;
51 private static final MethodHandle REFER_QUERY;
52
53 static {
54 MethodHandles.Lookup lookup;
55 try {
56 lookup = MethodHandles.privateLookupIn(ReteRecipeCompiler.class, MethodHandles.lookup());
57 } catch (IllegalAccessException e) {
58 throw new IllegalStateException("Failed to create lookup", e);
59 }
60 try {
61 GET_SUB_PLAN_COMPILER_CACHE = lookup.findGetter(ReteRecipeCompiler.class, "subPlanCompilerCache",
62 Map.class);
63 GET_COMPILER_BACK_TRACE = lookup.findGetter(ReteRecipeCompiler.class, "compilerBackTrace", Map.class);
64 } catch (NoSuchFieldException | IllegalAccessException e) {
65 throw new IllegalStateException("Failed to find getter", e);
66 }
67
68 try {
69 NORMALIZER_FIELD = ReteRecipeCompiler.class.getDeclaredField("normalizer");
70 } catch (NoSuchFieldException e) {
71 throw new IllegalStateException("Failed to find field", e);
72 }
73 NORMALIZER_FIELD.setAccessible(true);
74
75 try {
76 DO_COMPILE_DISPATCH = lookup.findVirtual(ReteRecipeCompiler.class, "doCompileDispatch",
77 MethodType.methodType(CompiledSubPlan.class, SubPlan.class));
78 COMPILE_TO_NATURAL_JOIN = lookup.findVirtual(ReteRecipeCompiler.class, "compileToNaturalJoin",
79 MethodType.methodType(CompiledSubPlan.class, SubPlan.class, PlanningTrace.class,
80 PlanningTrace.class));
81 REFER_QUERY = lookup.findVirtual(ReteRecipeCompiler.class, "referQuery",
82 MethodType.methodType(PlanningTrace.class, PQuery.class, SubPlan.class, Tuple.class));
83 } catch (NoSuchMethodException | IllegalAccessException e) {
84 throw new IllegalStateException("Failed to find method", e);
85 }
86 }
87
88 private final Map<SubPlan, CompiledSubPlan> subPlanCompilerCache;
89 private final Map<ReteNodeRecipe, SubPlan> compilerBackTrace;
90
91 public RefineryReteRecipeCompiler(IQueryPlannerStrategy plannerStrategy, Logger logger,
92 IQueryMetaContext metaContext, IQueryCacheContext queryCacheContext,
93 IQueryBackendHintProvider hintProvider, QueryAnalyzer queryAnalyzer,
94 boolean deleteAndReDeriveEvaluation, TimelyConfiguration timelyEvaluation) {
95 super(plannerStrategy, logger, metaContext, queryCacheContext, hintProvider, queryAnalyzer,
96 deleteAndReDeriveEvaluation, timelyEvaluation);
97
98 var normalizer = new PDisjunctionRewriterCacher(new RefinerySurrogateQueryRewriter(),
99 new RefineryPBodyNormalizer(metaContext) {
100
101 @Override
102 protected boolean shouldExpandWeakenedAlternatives(PQuery query) {
103 var hint = hintProvider.getQueryEvaluationHint(query);
104 return ReteHintOptions.expandWeakenedAlternativeConstraints.getValueOrDefault(hint);
105 }
106
107 });
108 try {
109 // https://docs.oracle.com/javase/specs/jls/se17/html/jls-17.html#jls-17.5.3
110 // "The object should not be made visible to other threads, nor should the final fields be read,
111 // until all updates to the final fields of the object are complete."
112 // The {@code super} constructor only sets but doesn't read the {@code normalizer} field,
113 // therefore this is fine.
114 NORMALIZER_FIELD.set(this, normalizer);
115 } catch (IllegalAccessException e) {
116 throw new IllegalStateException("Failed to set private final field", e);
117 }
118
119 try {
120 @SuppressWarnings("unchecked")
121 var cache = (Map<SubPlan, CompiledSubPlan>) GET_SUB_PLAN_COMPILER_CACHE.invokeExact(
122 (ReteRecipeCompiler) this);
123 subPlanCompilerCache = cache;
124 @SuppressWarnings("unchecked")
125 var backTrace = (Map<ReteNodeRecipe, SubPlan>) GET_COMPILER_BACK_TRACE.invokeExact(
126 (ReteRecipeCompiler) this);
127 compilerBackTrace = backTrace;
128 } catch (Error e) {
129 // Fatal JVM errors should not be wrapped.
130 throw e;
131 } catch (Throwable e) {
132 throw new IllegalStateException("Failed to access private fields", e);
133 }
134 }
135
136 @Override
137 public CompiledSubPlan getCompiledForm(SubPlan plan) {
138 CompiledSubPlan compiled = subPlanCompilerCache.get(plan);
139 if (compiled == null) {
140 compiled = doCompileDispatchExtension(plan);
141 if (compiled == null) {
142 compiled = superDoCompileDispatch(plan);
143 }
144 subPlanCompilerCache.put(plan, compiled);
145 compilerBackTrace.put(compiled.getRecipe(), plan);
146 }
147 return compiled;
148 }
149
150 @Nullable
151 private CompiledSubPlan doCompileDispatchExtension(SubPlan plan) {
152 var operation = plan.getOperation();
153 if (operation instanceof PEnumerate enumerateOperation) {
154 return doCompileEnumerateExtension(enumerateOperation.getEnumerablePConstraint(), plan);
155 } else if (operation instanceof PApply applyOperation &&
156 applyOperation.getPConstraint() instanceof EnumerablePConstraint constraint) {
157 var secondaryParent = doEnumerateDispatchExtension(plan, constraint);
158 if (secondaryParent != null) {
159 var primaryParent = getCompiledForm(plan.getParentPlans().get(0));
160 return superCompileToNaturalJoin(plan, primaryParent, secondaryParent);
161 }
162 }
163 return null;
164 }
165
166 @Nullable
167 private CompiledSubPlan doCompileEnumerateExtension(EnumerablePConstraint constraint, SubPlan plan) {
168 var coreTrace = doEnumerateDispatchExtension(plan, constraint);
169 if (coreTrace == null) {
170 return null;
171 }
172 var trimmedTrace = CompilerHelper.checkAndTrimEqualVariables(plan, coreTrace);
173 return trimmedTrace.cloneFor(plan);
174 }
175
176 @Nullable
177 private PlanningTrace doEnumerateDispatchExtension(SubPlan plan, EnumerablePConstraint constraint) {
178 if (constraint instanceof RepresentativeElectionConstraint representativeElectionConstraint) {
179 return compileEnumerableExtension(plan, representativeElectionConstraint);
180 }
181 return null;
182 }
183
184 private PlanningTrace compileEnumerableExtension(SubPlan plan, RepresentativeElectionConstraint constraint) {
185 var referredQuery = constraint.getSupplierKey();
186 var callTrace = superReferQuery(referredQuery, plan, constraint.getVariablesTuple());
187 var recipe = RefineryRecipesFactory.eINSTANCE.createRepresentativeElectionRecipe();
188 recipe.setParent(callTrace.getRecipe());
189 recipe.setConnectivity(constraint.getConnectivity());
190 return new PlanningTrace(plan, CompilerHelper.convertVariablesTuple(constraint), recipe, callTrace);
191 }
192
193 private CompiledSubPlan superDoCompileDispatch(SubPlan plan) {
194 try {
195 return (CompiledSubPlan) DO_COMPILE_DISPATCH.invokeExact((ReteRecipeCompiler) this, plan);
196 } catch (Error | RuntimeException e) {
197 // Fatal JVM errors and runtime exceptions should not be wrapped.
198 throw e;
199 } catch (Throwable e) {
200 throw new IllegalStateException("Failed to call doCompileDispatch", e);
201 }
202 }
203
204 private CompiledSubPlan superCompileToNaturalJoin(SubPlan plan, PlanningTrace leftCompiled,
205 PlanningTrace rightCompiled) {
206 try {
207 return (CompiledSubPlan) COMPILE_TO_NATURAL_JOIN.invokeExact((ReteRecipeCompiler) this, plan,
208 leftCompiled, rightCompiled);
209 } catch (Error | RuntimeException e) {
210 // Fatal JVM errors and runtime exceptions should not be wrapped.
211 throw e;
212 } catch (Throwable e) {
213 throw new IllegalStateException("Failed to call compileToNaturalJoin", e);
214 }
215 }
216
217 private PlanningTrace superReferQuery(PQuery query, SubPlan plan, Tuple actualParametersTuple) {
218 try {
219 return (PlanningTrace) REFER_QUERY.invokeExact((ReteRecipeCompiler) this, query, plan,
220 actualParametersTuple);
221 } catch (Error | RuntimeException e) {
222 // Fatal JVM errors and runtime exceptions should not be wrapped.
223 throw e;
224 } catch (Throwable e) {
225 throw new IllegalStateException("Failed to call referQuery", e);
226 }
227 }
228}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryConnectionFactoryExtensions.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryConnectionFactoryExtensions.java
new file mode 100644
index 00000000..0fe5ee27
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryConnectionFactoryExtensions.java
@@ -0,0 +1,47 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.network;
7
8import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
9import org.eclipse.viatra.query.runtime.rete.network.Node;
10import org.eclipse.viatra.query.runtime.rete.network.ReteContainer;
11import org.eclipse.viatra.query.runtime.rete.network.Supplier;
12import org.eclipse.viatra.query.runtime.rete.remote.Address;
13import org.eclipse.viatra.query.runtime.rete.traceability.RecipeTraceInfo;
14import tools.refinery.store.query.viatra.internal.rete.recipe.RepresentativeElectionRecipe;
15
16import java.util.ArrayList;
17
18public class RefineryConnectionFactoryExtensions {
19 private final ReteContainer reteContainer;
20
21 public RefineryConnectionFactoryExtensions(ReteContainer reteContainer) {
22 this.reteContainer = reteContainer;
23 }
24
25 public boolean connectToParents(RecipeTraceInfo recipeTrace, Node freshNode) {
26 var recipe = recipeTrace.getRecipe();
27 if (recipe instanceof RepresentativeElectionRecipe representativeElectionRecipe) {
28 connectToParents(representativeElectionRecipe, (RepresentativeElectionNode) freshNode);
29 return true;
30 }
31 return false;
32 }
33
34 private void connectToParents(RepresentativeElectionRecipe recipe, RepresentativeElectionNode freshNode) {
35 var parentRecipe = recipe.getParent();
36 // Apparently VIATRA ensures that this cast is safe, see
37 // {@link org.eclipse.viatra.query.runtime.rete.network.ConnectionFactory.connectToParent}.
38 @SuppressWarnings("unchecked")
39 var parentAddress = (Address<? extends Supplier>) reteContainer.getNetwork()
40 .getExistingNodeByRecipe(parentRecipe);
41 var parentSupplier = reteContainer.getProvisioner().asSupplier(parentAddress);
42 var tuples = new ArrayList<Tuple>();
43 parentSupplier.pullInto(tuples, true);
44 freshNode.reinitializeWith(tuples);
45 reteContainer.connect(parentSupplier, freshNode);
46 }
47}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryNodeFactoryExtensions.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryNodeFactoryExtensions.java
new file mode 100644
index 00000000..82b63a55
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RefineryNodeFactoryExtensions.java
@@ -0,0 +1,44 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.network;
7
8import org.eclipse.viatra.query.runtime.rete.network.ReteContainer;
9import org.eclipse.viatra.query.runtime.rete.network.Supplier;
10import org.eclipse.viatra.query.runtime.rete.recipes.ReteNodeRecipe;
11import org.eclipse.viatra.query.runtime.rete.traceability.TraceInfo;
12import org.jetbrains.annotations.Nullable;
13import tools.refinery.store.query.viatra.internal.rete.recipe.RepresentativeElectionRecipe;
14
15public class RefineryNodeFactoryExtensions {
16 @Nullable
17 public Supplier createNode(ReteContainer reteContainer, ReteNodeRecipe recipe, TraceInfo... traces) {
18 var result = instantiateNode(reteContainer, recipe);
19 if (result == null) {
20 return null;
21 }
22 for (var traceInfo : traces) {
23 result.assignTraceInfo(traceInfo);
24 }
25 return result;
26 }
27
28 @Nullable
29 private Supplier instantiateNode(ReteContainer reteContainer, ReteNodeRecipe recipe) {
30 if (recipe instanceof RepresentativeElectionRecipe representativeElectionRecipe) {
31 return instantiateRepresentativeElectionNode(reteContainer, representativeElectionRecipe);
32 }
33 return null;
34 }
35
36 private Supplier instantiateRepresentativeElectionNode(ReteContainer reteContainer,
37 RepresentativeElectionRecipe recipe) {
38 RepresentativeElectionAlgorithm.Factory algorithmFactory = switch (recipe.getConnectivity()) {
39 case STRONG -> StronglyConnectedComponentAlgorithm::new;
40 case WEAK -> WeaklyConnectedComponentAlgorithm::new;
41 };
42 return new RepresentativeElectionNode(reteContainer, algorithmFactory);
43 }
44}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionAlgorithm.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionAlgorithm.java
new file mode 100644
index 00000000..ff5c7158
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionAlgorithm.java
@@ -0,0 +1,137 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.network;
7
8import org.eclipse.viatra.query.runtime.base.itc.graphimpl.Graph;
9import org.eclipse.viatra.query.runtime.base.itc.igraph.IGraphObserver;
10import org.eclipse.viatra.query.runtime.matchers.util.Direction;
11
12import java.util.*;
13
14public abstract class RepresentativeElectionAlgorithm implements IGraphObserver<Object> {
15 protected final Graph<Object> graph;
16 protected final Map<Object, Object> representatives = new HashMap<>();
17 protected final Map<Object, Set<Object>> components = new HashMap<>();
18 private RepresentativeElectionNode observer;
19
20 protected RepresentativeElectionAlgorithm(Graph<Object> graph) {
21 this.graph = graph;
22 initializeComponents();
23 graph.attachObserver(this);
24 }
25
26 protected abstract void initializeComponents();
27
28 protected void initializeSet(Set<Object> set) {
29 var iterator = set.iterator();
30 if (!iterator.hasNext()) {
31 // Set is empty.
32 return;
33 }
34 var representative = iterator.next();
35 for (var node : set) {
36 var oldRepresentative = representatives.put(node, representative);
37 if (oldRepresentative != null && !representative.equals(oldRepresentative)) {
38 throw new IllegalStateException("Node %s is already in a set represented by %s, cannot add it to %s"
39 .formatted(node, oldRepresentative, set));
40 }
41 }
42 components.put(representative, set);
43 }
44
45 protected void merge(Object leftRepresentative, Object rightRepresentative) {
46 if (leftRepresentative.equals(rightRepresentative)) {
47 return;
48 }
49 var leftSet = getComponent(leftRepresentative);
50 var rightSet = getComponent(rightRepresentative);
51 if (leftSet.size() < rightSet.size()) {
52 merge(rightRepresentative, rightSet, leftRepresentative, leftSet);
53 } else {
54 merge(leftRepresentative, leftSet, rightRepresentative, rightSet);
55 }
56 }
57
58 private void merge(Object preservedRepresentative, Set<Object> preservedSet, Object removedRepresentative,
59 Set<Object> removedSet) {
60 components.remove(removedRepresentative);
61 for (var node : removedSet) {
62 representatives.put(node, preservedRepresentative);
63 preservedSet.add(node);
64 notifyToObservers(node, removedRepresentative, preservedRepresentative);
65 }
66 }
67
68 protected void assignNewRepresentative(Object oldRepresentative, Set<Object> set) {
69 var iterator = set.iterator();
70 if (!iterator.hasNext()) {
71 return;
72 }
73 var newRepresentative = iterator.next();
74 components.put(newRepresentative, set);
75 for (var node : set) {
76 var oldRepresentativeOfNode = representatives.put(node, newRepresentative);
77 if (!oldRepresentative.equals(oldRepresentativeOfNode)) {
78 throw new IllegalArgumentException("Node %s was not represented by %s but by %s"
79 .formatted(node, oldRepresentative, oldRepresentativeOfNode));
80 }
81 notifyToObservers(node, oldRepresentative, newRepresentative);
82 }
83 }
84
85 public void setObserver(RepresentativeElectionNode observer) {
86 this.observer = observer;
87 }
88
89 public Map<Object, Set<Object>> getComponents() {
90 return components;
91 }
92
93 public Object getRepresentative(Object node) {
94 return representatives.get(node);
95 }
96
97 public Set<Object> getComponent(Object representative) {
98 return components.get(representative);
99 }
100
101 public void dispose() {
102 graph.detachObserver(this);
103 }
104
105 @Override
106 public void nodeInserted(Object n) {
107 var component = new HashSet<>(1);
108 component.add(n);
109 initializeSet(component);
110 notifyToObservers(n, n, Direction.INSERT);
111 }
112
113 @Override
114 public void nodeDeleted(Object n) {
115 var representative = representatives.remove(n);
116 if (!representative.equals(n)) {
117 throw new IllegalStateException("Trying to delete node with dangling edges");
118 }
119 components.remove(representative);
120 notifyToObservers(n, representative, Direction.DELETE);
121 }
122
123 protected void notifyToObservers(Object node, Object oldRepresentative, Object newRepresentative) {
124 notifyToObservers(node, oldRepresentative, Direction.DELETE);
125 notifyToObservers(node, newRepresentative, Direction.INSERT);
126 }
127
128 protected void notifyToObservers(Object node, Object representative, Direction direction) {
129 if (observer != null) {
130 observer.tupleChanged(node, representative, direction);
131 }
132 }
133
134 interface Factory {
135 RepresentativeElectionAlgorithm create(Graph<Object> graph);
136 }
137}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionNode.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionNode.java
new file mode 100644
index 00000000..701f6ffe
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/RepresentativeElectionNode.java
@@ -0,0 +1,120 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2012, Tamas Szabo, Gabor Bergmann, Istvan Rath and Daniel Varro
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v. 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-v20.html.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.store.query.viatra.internal.rete.network;
10
11import org.eclipse.viatra.query.runtime.base.itc.graphimpl.Graph;
12import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
13import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
14import org.eclipse.viatra.query.runtime.matchers.util.Clearable;
15import org.eclipse.viatra.query.runtime.matchers.util.Direction;
16import org.eclipse.viatra.query.runtime.matchers.util.timeline.Timeline;
17import org.eclipse.viatra.query.runtime.rete.network.ReteContainer;
18import org.eclipse.viatra.query.runtime.rete.network.communication.Timestamp;
19import org.eclipse.viatra.query.runtime.rete.single.SingleInputNode;
20
21import java.util.Collection;
22import java.util.Map;
23
24public class RepresentativeElectionNode extends SingleInputNode implements Clearable {
25 private final RepresentativeElectionAlgorithm.Factory algorithmFactory;
26 private Graph<Object> graph;
27 private RepresentativeElectionAlgorithm algorithm;
28
29 public RepresentativeElectionNode(ReteContainer reteContainer,
30 RepresentativeElectionAlgorithm.Factory algorithmFactory) {
31 super(reteContainer);
32 this.algorithmFactory = algorithmFactory;
33 graph = new Graph<>();
34 algorithm = algorithmFactory.create(graph);
35 algorithm.setObserver(this);
36 reteContainer.registerClearable(this);
37 }
38
39 @Override
40 public void networkStructureChanged() {
41 if (reteContainer.isTimelyEvaluation() && reteContainer.getCommunicationTracker().isInRecursiveGroup(this)) {
42 throw new IllegalStateException(this + " cannot be used in recursive differential dataflow evaluation!");
43 }
44 super.networkStructureChanged();
45 }
46
47 public void reinitializeWith(Collection<Tuple> tuples) {
48 algorithm.dispose();
49 graph = new Graph<>();
50 for (var tuple : tuples) {
51 insertEdge(tuple.get(0), tuple.get(1));
52 }
53 algorithm = algorithmFactory.create(graph);
54 algorithm.setObserver(this);
55 }
56
57 public void tupleChanged(Object source, Object representative, Direction direction) {
58 var tuple = Tuples.staticArityFlatTupleOf(source, representative);
59 propagateUpdate(direction, tuple, Timestamp.ZERO);
60 }
61
62 @Override
63 public void clear() {
64 algorithm.dispose();
65 graph = new Graph<>();
66 algorithm = algorithmFactory.create(graph);
67 }
68
69 @Override
70 public void update(Direction direction, Tuple updateElement, Timestamp timestamp) {
71 var source = updateElement.get(0);
72 var target = updateElement.get(1);
73 switch (direction) {
74 case INSERT -> insertEdge(source, target);
75 case DELETE -> deleteEdge(source, target);
76 default -> throw new IllegalArgumentException("Unknown direction: " + direction);
77 }
78 }
79
80 private void insertEdge(Object source, Object target) {
81 graph.insertNode(source);
82 graph.insertNode(target);
83 graph.insertEdge(source, target);
84 }
85
86 private void deleteEdge(Object source, Object target) {
87 graph.deleteEdgeIfExists(source, target);
88 if (isIsolated(source)) {
89 graph.deleteNode(source);
90 }
91 if (!source.equals(target) && isIsolated(target)) {
92 graph.deleteNode(target);
93 }
94 }
95
96 private boolean isIsolated(Object node) {
97 return graph.getTargetNodes(node).isEmpty() && graph.getSourceNodes(node).isEmpty();
98 }
99
100 @Override
101 public void pullInto(Collection<Tuple> collector, boolean flush) {
102 for (var entry : algorithm.getComponents().entrySet()) {
103 var representative = entry.getKey();
104 for (var node : entry.getValue()) {
105 collector.add(Tuples.staticArityFlatTupleOf(node, representative));
106 }
107 }
108 }
109
110 @Override
111 public void pullIntoWithTimeline(Map<Tuple, Timeline<Timestamp>> collector, boolean flush) {
112 // Use all zero timestamps because this node cannot be used in recursive groups anyway.
113 for (var entry : algorithm.getComponents().entrySet()) {
114 var representative = entry.getKey();
115 for (var node : entry.getValue()) {
116 collector.put(Tuples.staticArityFlatTupleOf(node, representative), Timestamp.INSERT_AT_ZERO_TIMELINE);
117 }
118 }
119 }
120}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/StronglyConnectedComponentAlgorithm.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/StronglyConnectedComponentAlgorithm.java
new file mode 100644
index 00000000..11155f3e
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/StronglyConnectedComponentAlgorithm.java
@@ -0,0 +1,66 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.network;
7
8import org.eclipse.viatra.query.runtime.base.itc.alg.misc.GraphHelper;
9import org.eclipse.viatra.query.runtime.base.itc.alg.misc.bfs.BFS;
10import org.eclipse.viatra.query.runtime.base.itc.alg.misc.scc.SCC;
11import org.eclipse.viatra.query.runtime.base.itc.graphimpl.Graph;
12
13import java.util.Collection;
14import java.util.Set;
15
16public class StronglyConnectedComponentAlgorithm extends RepresentativeElectionAlgorithm {
17 public StronglyConnectedComponentAlgorithm(Graph<Object> graph) {
18 super(graph);
19 }
20
21 @Override
22 protected void initializeComponents() {
23 var computedSCCs = SCC.computeSCC(graph).getSccs();
24 for (var computedSCC : computedSCCs) {
25 initializeSet(computedSCC);
26 }
27 }
28
29 @Override
30 public void edgeInserted(Object source, Object target) {
31 var sourceRoot = getRepresentative(source);
32 var targetRoot = getRepresentative(target);
33 if (sourceRoot.equals(targetRoot)) {
34 // New edge does not change strongly connected components.
35 return;
36 }
37 if (BFS.isReachable(target, source, graph)) {
38 merge(sourceRoot, targetRoot);
39 }
40 }
41
42 @Override
43 public void edgeDeleted(Object source, Object target) {
44 var sourceRoot = getRepresentative(source);
45 var targetRoot = getRepresentative(target);
46 if (!sourceRoot.equals(targetRoot)) {
47 // New edge does not change strongly connected components.
48 return;
49 }
50 var component = GraphHelper.getSubGraph(getComponent(sourceRoot), graph);
51 if (!BFS.isReachable(source, target, component)) {
52 var newSCCs = SCC.computeSCC(component).getSccs();
53 split(sourceRoot, newSCCs);
54 }
55 }
56
57 private void split(Object preservedRepresentative, Collection<? extends Set<Object>> sets) {
58 for (var set : sets) {
59 if (set.contains(preservedRepresentative)) {
60 components.put(preservedRepresentative, set);
61 } else {
62 assignNewRepresentative(preservedRepresentative, set);
63 }
64 }
65 }
66}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/WeaklyConnectedComponentAlgorithm.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/WeaklyConnectedComponentAlgorithm.java
new file mode 100644
index 00000000..118004dd
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/network/WeaklyConnectedComponentAlgorithm.java
@@ -0,0 +1,85 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.network;
7
8import org.eclipse.viatra.query.runtime.base.itc.graphimpl.Graph;
9
10import java.util.ArrayDeque;
11import java.util.HashSet;
12import java.util.Set;
13
14public class WeaklyConnectedComponentAlgorithm extends RepresentativeElectionAlgorithm {
15 public WeaklyConnectedComponentAlgorithm(Graph<Object> graph) {
16 super(graph);
17 }
18
19 @Override
20 protected void initializeComponents() {
21 for (var node : graph.getAllNodes()) {
22 if (representatives.containsKey(node)) {
23 continue;
24 }
25 var reachable = getReachableNodes(node);
26 initializeSet(reachable);
27 }
28 }
29
30 @Override
31 public void edgeInserted(Object source, Object target) {
32 var sourceRoot = getRepresentative(source);
33 var targetRoot = getRepresentative(target);
34 merge(sourceRoot, targetRoot);
35 }
36
37 @Override
38 public void edgeDeleted(Object source, Object target) {
39 var sourceRoot = getRepresentative(source);
40 var targetRoot = getRepresentative(target);
41 if (!sourceRoot.equals(targetRoot)) {
42 throw new IllegalArgumentException("Trying to remove edge not in graph");
43 }
44 var targetReachable = getReachableNodes(target);
45 if (!targetReachable.contains(source)) {
46 split(sourceRoot, targetReachable);
47 }
48 }
49
50 private void split(Object sourceRepresentative, Set<Object> targetReachable) {
51 var sourceComponent = getComponent(sourceRepresentative);
52 sourceComponent.removeAll(targetReachable);
53 if (targetReachable.contains(sourceRepresentative)) {
54 components.put(sourceRepresentative, targetReachable);
55 assignNewRepresentative(sourceRepresentative, sourceComponent);
56 } else {
57 assignNewRepresentative(sourceRepresentative, targetReachable);
58 }
59 }
60
61 private Set<Object> getReachableNodes(Object source) {
62 var retSet = new HashSet<>();
63 retSet.add(source);
64 var nodeQueue = new ArrayDeque<>();
65 nodeQueue.addLast(source);
66
67 while (!nodeQueue.isEmpty()) {
68 var node = nodeQueue.removeFirst();
69 for (var neighbor : graph.getTargetNodes(node).distinctValues()) {
70 if (!retSet.contains(neighbor)) {
71 retSet.add(neighbor);
72 nodeQueue.addLast(neighbor);
73 }
74 }
75 for (var neighbor : graph.getSourceNodes(node).distinctValues()) {
76 if (!retSet.contains(neighbor)) {
77 retSet.add(neighbor);
78 nodeQueue.addLast(neighbor);
79 }
80 }
81 }
82
83 return retSet;
84 }
85}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactory.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactory.java
new file mode 100644
index 00000000..1f8b3034
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactory.java
@@ -0,0 +1,22 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.recipe;
7
8import org.eclipse.emf.ecore.EDataType;
9import org.eclipse.emf.ecore.EFactory;
10import tools.refinery.store.query.literal.Connectivity;
11
12// Naming and index computation follows EMF conventions.
13@SuppressWarnings("squid:S115")
14public interface RefineryRecipesFactory extends EFactory {
15 RefineryRecipesFactory eINSTANCE = RefineryRecipesFactoryImpl.init();
16
17 RepresentativeElectionRecipe createRepresentativeElectionRecipe();
18
19 Connectivity createConnectivityFromString(EDataType eDataType, String initialValue);
20
21 String convertConnectivityToString(EDataType eDataType, Object instanceValue);
22}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactoryImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactoryImpl.java
new file mode 100644
index 00000000..4e2a695c
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesFactoryImpl.java
@@ -0,0 +1,74 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.recipe;
7
8import org.eclipse.emf.ecore.EClass;
9import org.eclipse.emf.ecore.EDataType;
10import org.eclipse.emf.ecore.EObject;
11import org.eclipse.emf.ecore.EPackage;
12import org.eclipse.emf.ecore.impl.EFactoryImpl;
13import org.eclipse.emf.ecore.plugin.EcorePlugin;
14import tools.refinery.store.query.literal.Connectivity;
15
16public class RefineryRecipesFactoryImpl extends EFactoryImpl implements RefineryRecipesFactory {
17 public static RefineryRecipesFactory init() {
18 try {
19 var factory = (RefineryRecipesFactory) EPackage.Registry.INSTANCE.getEFactory(
20 RefineryRecipesPackage.eNS_URI);
21 if (factory != null) {
22 return factory;
23 }
24 }
25 catch (Exception exception) {
26 EcorePlugin.INSTANCE.log(exception);
27 }
28 return new RefineryRecipesFactoryImpl();
29 }
30
31 @Override
32 public EObject create(EClass eClass) {
33 if (eClass.getClassifierID() == RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE) {
34 return createRepresentativeElectionRecipe();
35 } else {
36 throw new IllegalArgumentException("The class '%s' is not a valid classifier".formatted(eClass.getName()));
37 }
38 }
39
40 @Override
41 public Object createFromString(EDataType eDataType, String stringValue) {
42 if (eDataType.getClassifierID() == RefineryRecipesPackage.CONNECTIVITY) {
43 return createConnectivityFromString(eDataType, stringValue);
44 } else {
45 throw new IllegalArgumentException("The datatype '%s' is not a valid classifier"
46 .formatted(eDataType.getName()));
47 }
48 }
49
50 @Override
51 public String convertToString(EDataType eDataType, Object objectValue) {
52 if (eDataType.getClassifierID() == RefineryRecipesPackage.CONNECTIVITY) {
53 return convertConnectivityToString(eDataType, objectValue);
54 } else {
55 throw new IllegalArgumentException("The datatype '%s' is not a valid classifier"
56 .formatted(eDataType.getName()));
57 }
58 }
59
60 @Override
61 public RepresentativeElectionRecipe createRepresentativeElectionRecipe() {
62 return new RepresentativeElectionRecipeImpl();
63 }
64
65 @Override
66 public Connectivity createConnectivityFromString(EDataType eDataType, String initialValue) {
67 return (Connectivity) super.createFromString(eDataType, initialValue);
68 }
69
70 @Override
71 public String convertConnectivityToString(EDataType eDataType, Object instanceValue) {
72 return super.convertToString(eDataType, instanceValue);
73 }
74}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackage.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackage.java
new file mode 100644
index 00000000..6c933c45
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackage.java
@@ -0,0 +1,41 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.recipe;
7
8import org.eclipse.emf.ecore.*;
9import org.eclipse.viatra.query.runtime.rete.recipes.RecipesPackage;
10
11// Naming and index computation follows EMF conventions.
12@SuppressWarnings({"squid:S100", "squid:S115", "PointlessArithmeticExpression"})
13public interface RefineryRecipesPackage extends EPackage {
14 String eNAME = "refineryReteRecipes";
15
16 String eNS_URI = "https://refinery.tools/emf/2021/RefineryReteRecipes";
17
18 String eNS_PREFIX = "refineryReteRecipes";
19
20 RefineryRecipesPackage eINSTANCE = RefineryRecipesPackageImpl.init();
21
22 int REPRESENTATIVE_ELECTION_RECIPE = 0;
23
24 int REPRESENTATIVE_ELECTION_RECIPE__CONNECTIVITY = RecipesPackage.ALPHA_RECIPE_FEATURE_COUNT + 0;
25
26 int REPRESENTATIVE_ELECTION_RECIPE_FEATURE_COUNT = RecipesPackage.ALPHA_RECIPE_FEATURE_COUNT + 1;
27
28 int REPRESENTATIVE_ELECTION_RECIPE__GET_ARITY = RecipesPackage.ALPHA_RECIPE_OPERATION_COUNT + 0;
29
30 int REPRESENTATIVE_ELECTION_RECIPE_OPERATION_COUNT = RecipesPackage.ALPHA_RECIPE_OPERATION_COUNT + 1;
31
32 int CONNECTIVITY = 1;
33
34 EClass getRepresentativeElectionRecipe();
35
36 EAttribute getRepresentativeElectionRecipe_Connectivity();
37
38 EOperation getRepresentativeElectionRecipe_GetArity();
39
40 EDataType getConnectivity();
41}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackageImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackageImpl.java
new file mode 100644
index 00000000..d5073402
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RefineryRecipesPackageImpl.java
@@ -0,0 +1,96 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.recipe;
7
8import org.eclipse.emf.ecore.*;
9import org.eclipse.emf.ecore.impl.EPackageImpl;
10import org.eclipse.viatra.query.runtime.rete.recipes.RecipesPackage;
11import tools.refinery.store.query.literal.Connectivity;
12
13public class RefineryRecipesPackageImpl extends EPackageImpl implements RefineryRecipesPackage {
14 private static boolean isInstanceInitialized;
15 private boolean isCreated;
16 private boolean isInitialized;
17 private EClass representativeElectionRecipe;
18 private EDataType connectivity;
19
20 public static RefineryRecipesPackage init() {
21 if (isInstanceInitialized) {
22 return (RefineryRecipesPackage) Registry.INSTANCE.getEPackage(eNS_URI);
23 }
24 var thePackage = Registry.INSTANCE.get(eNS_URI) instanceof RefineryRecipesPackageImpl impl ? impl :
25 new RefineryRecipesPackageImpl();
26 isInstanceInitialized = true;
27 thePackage.createPackageContents();
28 thePackage.initializePackageContents();
29 thePackage.freeze();
30 Registry.INSTANCE.put(eNS_URI, thePackage);
31 return thePackage;
32 }
33
34 private RefineryRecipesPackageImpl() {
35 super(eNS_URI, RefineryRecipesFactory.eINSTANCE);
36 }
37
38 @Override
39 public EClass getRepresentativeElectionRecipe() {
40 return representativeElectionRecipe;
41 }
42
43 @Override
44 public EAttribute getRepresentativeElectionRecipe_Connectivity() {
45 return (EAttribute) representativeElectionRecipe.getEStructuralFeatures().get(0);
46 }
47
48 @Override
49 public EOperation getRepresentativeElectionRecipe_GetArity() {
50 return representativeElectionRecipe.getEOperations().get(0);
51 }
52
53 @Override
54 public EDataType getConnectivity() {
55 return connectivity;
56 }
57
58 public void createPackageContents() {
59 if (isCreated) {
60 return;
61 }
62 isCreated = true;
63
64 representativeElectionRecipe = createEClass(REPRESENTATIVE_ELECTION_RECIPE);
65 createEAttribute(representativeElectionRecipe, REPRESENTATIVE_ELECTION_RECIPE__CONNECTIVITY);
66 createEOperation(representativeElectionRecipe, REPRESENTATIVE_ELECTION_RECIPE__GET_ARITY);
67
68 connectivity = createEDataType(CONNECTIVITY);
69 }
70
71 public void initializePackageContents() {
72 if (isInitialized) {
73 return;
74 }
75 isInitialized = true;
76
77 setName(eNAME);
78 setNsPrefix(eNS_PREFIX);
79 setNsURI(eNS_URI);
80
81 representativeElectionRecipe.getESuperTypes().add(RecipesPackage.Literals.ALPHA_RECIPE);
82
83 initEClass(representativeElectionRecipe, RepresentativeElectionRecipe.class,
84 "RepresentativeElectionRecipe", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
85 initEAttribute(getRepresentativeElectionRecipe_Connectivity(), getConnectivity(), "connectivity", null, 0, 1,
86 RepresentativeElectionRecipe.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID,
87 IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
88 initEOperation(getRepresentativeElectionRecipe_GetArity(), EcorePackage.Literals.EINT, "getArity", 0, 1,
89 !IS_UNIQUE, IS_ORDERED);
90
91 initEDataType(connectivity, Connectivity.class, "Connectivity", IS_SERIALIZABLE,
92 !IS_GENERATED_INSTANCE_CLASS);
93
94 createResource(eNS_URI);
95 }
96}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipe.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipe.java
new file mode 100644
index 00000000..def825c2
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipe.java
@@ -0,0 +1,17 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.recipe;
7
8import org.eclipse.viatra.query.runtime.rete.recipes.AlphaRecipe;
9import tools.refinery.store.query.literal.Connectivity;
10
11public interface RepresentativeElectionRecipe extends AlphaRecipe {
12 Connectivity getConnectivity();
13
14 void setConnectivity(Connectivity connectivity);
15
16 int getArity();
17}
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipeImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipeImpl.java
new file mode 100644
index 00000000..959836d2
--- /dev/null
+++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/rete/recipe/RepresentativeElectionRecipeImpl.java
@@ -0,0 +1,105 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.query.viatra.internal.rete.recipe;
7
8import org.eclipse.emf.common.notify.Notification;
9import org.eclipse.emf.common.util.EList;
10import org.eclipse.emf.ecore.EClass;
11import org.eclipse.emf.ecore.impl.ENotificationImpl;
12import org.eclipse.viatra.query.runtime.rete.recipes.RecipesPackage;
13import org.eclipse.viatra.query.runtime.rete.recipes.ReteNodeRecipe;
14import org.eclipse.viatra.query.runtime.rete.recipes.impl.AlphaRecipeImpl;
15import tools.refinery.store.query.literal.Connectivity;
16
17import java.lang.reflect.InvocationTargetException;
18
19public class RepresentativeElectionRecipeImpl extends AlphaRecipeImpl implements RepresentativeElectionRecipe {
20 private Connectivity connectivity;
21
22 @Override
23 protected EClass eStaticClass() {
24 return RefineryRecipesPackage.eINSTANCE.getRepresentativeElectionRecipe();
25 }
26
27 @Override
28 public Connectivity getConnectivity() {
29 return connectivity;
30 }
31
32 @Override
33 public void setConnectivity(Connectivity newStrong) {
34 var oldConnectivity = connectivity;
35 connectivity = newStrong;
36 if (eNotificationRequired()) {
37 eNotify(new ENotificationImpl(this, Notification.SET,
38 RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE__CONNECTIVITY, oldConnectivity,
39 connectivity));
40 }
41 }
42
43 @Override
44 public int getArity() {
45 return 2;
46 }
47
48 @Override
49 public Object eGet(int featureID, boolean resolve, boolean coreType) {
50 if (featureID == RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE__CONNECTIVITY) {
51 return getConnectivity();
52 }
53 return super.eGet(featureID, resolve, coreType);
54 }
55
56 @Override
57 public void eSet(int featureID, Object newValue) {
58 if (featureID == RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE__CONNECTIVITY) {
59 setConnectivity((Connectivity) newValue);
60 } else {
61 super.eSet(featureID, newValue);
62 }
63 }
64
65 @Override
66 public void eUnset(int featureID) {
67 if (featureID == RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE__CONNECTIVITY) {
68 setConnectivity(null);
69 } else {
70 super.eUnset(featureID);
71 }
72 }
73
74 @Override
75 public boolean eIsSet(int featureID) {
76 if (featureID == RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE__CONNECTIVITY) {
77 return connectivity != null;
78 }
79 return super.eIsSet(featureID);
80 }
81
82 @Override
83 public int eDerivedOperationID(int baseOperationID, Class<?> baseClass) {
84 if (baseClass == ReteNodeRecipe.class && baseOperationID == RecipesPackage.RETE_NODE_RECIPE___GET_ARITY) {
85 return RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE__GET_ARITY;
86 }
87 return super.eDerivedOperationID(baseOperationID, baseClass);
88 }
89
90 @Override
91 public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException {
92 if (operationID == RefineryRecipesPackage.REPRESENTATIVE_ELECTION_RECIPE__GET_ARITY) {
93 return getArity();
94 }
95 return super.eInvoke(operationID, arguments);
96 }
97
98 @Override
99 public String toString() {
100 if (eIsProxy()) {
101 return super.toString();
102 }
103 return "%s (connectivity: %s)".formatted(super.toString(), connectivity);
104 }
105}