aboutsummaryrefslogtreecommitdiffstats
path: root/store/src/main/java/org/eclipse/viatra/solver/data/query/internal
diff options
context:
space:
mode:
Diffstat (limited to 'store/src/main/java/org/eclipse/viatra/solver/data/query/internal')
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java59
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/PredicateTranslator.java209
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java51
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java63
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java32
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java57
-rw-r--r--store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java187
7 files changed, 658 insertions, 0 deletions
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java
new file mode 100644
index 00000000..042ec3dc
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java
@@ -0,0 +1,59 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.lang.reflect.InvocationTargetException;
4import java.util.concurrent.Callable;
5
6import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex;
7import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener;
8import org.eclipse.viatra.query.runtime.api.scope.IInstanceObserver;
9import org.eclipse.viatra.query.runtime.api.scope.ViatraBaseIndexChangeListener;
10
11/**
12 * copied from org.eclipse.viatra.query.runtime.tabular.TabularEngineContext;
13 */
14public class DummyBaseIndexer implements IBaseIndex{
15
16 @Override
17 public <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException {
18 try {
19 return callable.call();
20 } catch (Exception e) {
21 throw new InvocationTargetException(e);
22 }
23 }
24
25 @Override
26 public void addBaseIndexChangeListener(ViatraBaseIndexChangeListener listener) {
27 // no notification support
28 }
29
30 @Override
31 public void removeBaseIndexChangeListener(ViatraBaseIndexChangeListener listener) {
32 // no notification support
33 }
34
35 @Override
36 public void resampleDerivedFeatures() {
37 throw new UnsupportedOperationException();
38 }
39
40 @Override
41 public boolean addIndexingErrorListener(IIndexingErrorListener listener) {
42 return true;
43 }
44
45 @Override
46 public boolean removeIndexingErrorListener(IIndexingErrorListener listener) {
47 return true;
48 }
49
50 @Override
51 public boolean addInstanceObserver(IInstanceObserver observer, Object observedObject) {
52 return true;
53 }
54
55 @Override
56 public boolean removeInstanceObserver(IInstanceObserver observer, Object observedObject) {
57 return true;
58 }
59}
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/PredicateTranslator.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/PredicateTranslator.java
new file mode 100644
index 00000000..54cb4bab
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/PredicateTranslator.java
@@ -0,0 +1,209 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.LinkedHashSet;
6import java.util.LinkedList;
7import java.util.List;
8import java.util.Map;
9import java.util.Set;
10
11import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher;
12import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification;
13import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
14import org.eclipse.viatra.query.runtime.api.scope.QueryScope;
15import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint;
16import org.eclipse.viatra.query.runtime.matchers.psystem.PBody;
17import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable;
18import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality;
19import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter;
20import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality;
21import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall;
22import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryReflexiveTransitiveClosure;
23import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure;
24import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall;
25import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint;
26import org.eclipse.viatra.query.runtime.matchers.psystem.queries.BasePQuery;
27import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter;
28import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery;
29import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility;
30import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
31import org.eclipse.viatra.solver.data.query.RelationalScope;
32import org.eclipse.viatra.solver.data.query.view.RelationView;
33
34public class PredicateTranslator extends BasePQuery {
35
36 private final Map<String, PParameter> parameters = new HashMap<String, PParameter>();
37 private String fullyQualifiedName;
38 private LinkedList<PBody> bodies = new LinkedList<PBody>();
39 private List<ExportedParameter> symbolicParameters;
40
41 public PredicateTranslator(String fullyQualifiedName) {
42 super(PVisibility.PUBLIC);
43 this.fullyQualifiedName = fullyQualifiedName;
44 PBody body = new PBody(this);
45 bodies.add(body);
46 }
47
48 @Override
49 public String getFullyQualifiedName() {
50 return fullyQualifiedName;
51 }
52
53 public PredicateTranslator addParameter(String name, RelationView<?> type) {
54 PParameter parameter = new PParameter(name);
55 parameters.put(name, parameter);
56
57 PBody body = bodies.peekLast();
58 List<ExportedParameter> symbolicParameters = new ArrayList<>();
59 parameters.forEach((pName, pParameter) -> {
60 PVariable var = body.getOrCreateVariableByName(pName);
61 symbolicParameters.add(new ExportedParameter(body, var, pParameter));
62 });
63 body.setSymbolicParameters(symbolicParameters);
64
65 return this;
66 }
67
68 @Override
69 public List<PParameter> getParameters() {
70 return new ArrayList<PParameter>(parameters.values());
71 }
72 public <D> PredicateTranslator addConstraint(RelationView<D> view, String... name) {
73 if(name.length != view.getArity()) {
74 throw new IllegalArgumentException("Arity ("+view.getArity()+") does not match parameter numbers ("+name.length+")");
75 }
76 PBody body = bodies.peekLast();
77 Object[] variables = new Object[name.length];
78 for(int i = 0; i<name.length; i++) {
79 variables[i] = body.getOrCreateVariableByName(name[i]);
80 }
81 new TypeConstraint(body, Tuples.flatTupleOf(variables), view);
82 return this;
83 }
84
85// // Type constraint
86// public RelationQuery addConstraint(String type, String name) {
87// PBody body = bodies.peekLast();
88// PVariable var = body.getOrCreateVariableByName(name);
89// new TypeConstraint(body, Tuples.flatTupleOf(var), new StringExactInstancesKey(type));
90// return this;
91// }
92//
93// // Relation constraint
94// public RelationQuery addConstraint(String type, String sourceName, String targetName) {
95// PBody body = bodies.peekLast();
96// PVariable var_source = body.getOrCreateVariableByName(sourceName);
97// PVariable var_target = body.getOrCreateVariableByName(targetName);
98// new TypeConstraint(body, Tuples.flatTupleOf(var_source, var_target),
99// new StringStructuralFeatureInstancesKey(type));
100// return this;
101// }
102
103 // Create new Body
104 public PredicateTranslator or() {
105 PBody body = new PBody(this);
106 List<ExportedParameter> symbolicParameters = new ArrayList<>();
107 parameters.forEach((name, parameter) -> {
108 PVariable var = body.getOrCreateVariableByName(name);
109 symbolicParameters.add(new ExportedParameter(body, var, parameter));
110 });
111 body.setSymbolicParameters(symbolicParameters);
112 bodies.add(body);
113 return this;
114 }
115
116 // Equality constraint
117 public PredicateTranslator addEquality(String sourceName, String targetName) {
118 PBody body = bodies.peekLast();
119 PVariable var_source = body.getOrCreateVariableByName(sourceName);
120 PVariable var_target = body.getOrCreateVariableByName(targetName);
121 new Equality(body, var_source, var_target);
122 return this;
123 }
124
125 // Inequality constraint
126 public PredicateTranslator addInequality(String sourceName, String targetName) {
127 PBody body = bodies.peekLast();
128 PVariable var_source = body.getOrCreateVariableByName(sourceName);
129 PVariable var_target = body.getOrCreateVariableByName(targetName);
130 new Inequality(body, var_source, var_target);
131 return this;
132 }
133
134 // Positive pattern call
135 public PredicateTranslator addPatternCall(PQuery query, String... names) {
136 PBody body = bodies.peekLast();
137 PVariable[] vars = new PVariable[names.length];
138 for (int i = 0; i < names.length; i++) {
139 vars[i] = body.getOrCreateVariableByName(names[i]);
140 }
141 new PositivePatternCall(body, Tuples.flatTupleOf(vars), query);
142 return this;
143 }
144
145 // Negative pattern call
146 public PredicateTranslator addNegativePatternCall(PQuery query, String... names) {
147 PBody body = bodies.peekLast();
148 PVariable[] vars = new PVariable[names.length];
149 for (int i = 0; i < names.length; i++) {
150 vars[i] = body.getOrCreateVariableByName(names[i]);
151 }
152 new NegativePatternCall(body, Tuples.flatTupleOf(vars), query);
153 return this;
154 }
155
156 // Binary transitive closure pattern call
157 public PredicateTranslator addBinaryTransitiveClosure(PQuery query, String sourceName, String targetName) {
158 PBody body = bodies.peekLast();
159 PVariable var_source = body.getOrCreateVariableByName(sourceName);
160 PVariable var_target = body.getOrCreateVariableByName(targetName);
161 new BinaryTransitiveClosure(body, Tuples.flatTupleOf(var_source, var_target), query);
162 return this;
163 }
164
165 // Binary reflexive transitive closure pattern call
166 public PredicateTranslator addBinaryReflexiveTransitiveClosure(PQuery query, String sourceName, String targetName) {
167 PBody body = bodies.peekLast();
168 PVariable var_source = body.getOrCreateVariableByName(sourceName);
169 PVariable var_target = body.getOrCreateVariableByName(targetName);
170 new BinaryReflexiveTransitiveClosure(body, Tuples.flatTupleOf(var_source, var_target), query,
171 query.getParameters().get(0).getDeclaredUnaryType());
172 return this;
173 }
174
175 @Override
176 public Set<PBody> doGetContainedBodies() {
177 setEvaluationHints(new QueryEvaluationHint(null, QueryEvaluationHint.BackendRequirement.UNSPECIFIED));
178 return new LinkedHashSet<PBody>(bodies);
179 }
180
181 public void addSymbolicParameters(ExportedParameter symbolicParameter) {
182 checkMutability();
183 if (symbolicParameters == null) {
184 symbolicParameters = new ArrayList<>();
185 }
186 symbolicParameters.add(symbolicParameter);
187 }
188
189 public GenericQuerySpecification<GenericPatternMatcher> build() {
190 return new GenericQuerySpecification<GenericPatternMatcher>(this) {
191
192 @Override
193 public Class<? extends QueryScope> getPreferredScopeClass() {
194 return RelationalScope.class;
195 }
196
197 @Override
198 protected GenericPatternMatcher instantiate(ViatraQueryEngine engine) {
199 return defaultInstantiate(engine);
200 }
201
202 @Override
203 public GenericPatternMatcher instantiate() {
204 return new GenericPatternMatcher(this);
205 }
206
207 };
208 }
209} \ No newline at end of file
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java
new file mode 100644
index 00000000..c6d12614
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java
@@ -0,0 +1,51 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.HashMap;
4import java.util.HashSet;
5import java.util.Map;
6import java.util.Set;
7
8import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener;
9import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
10import org.eclipse.viatra.solver.data.model.Tuple;
11import org.eclipse.viatra.solver.data.query.view.RelationView;
12
13public class RelationUpdateListener {
14 private final Map<RelationView<?>,Set<RelationUpdateListenerEntry<?>>> view2Listeners;
15
16 public RelationUpdateListener(Set<RelationView<?>> relationViews) {
17 view2Listeners = new HashMap<>();
18 for(RelationView<?> relationView : relationViews) {
19 view2Listeners.put(relationView, new HashSet<>());
20 }
21 }
22 public boolean containsRelationalView(RelationView<?> relationalKey) {
23 RelationView<?> relationView = relationalKey.getWrappedKey();
24 return view2Listeners.containsKey(relationView);
25 }
26 public void addListener(RelationView<?> relationalKey, ITuple seed, IQueryRuntimeContextListener listener) {
27 RelationView<?> relationView = relationalKey.getWrappedKey();
28 if(view2Listeners.containsKey(relationView)) {
29 RelationUpdateListenerEntry<?> entry = new RelationUpdateListenerEntry<>(relationalKey, seed, listener);
30 view2Listeners.get(relationView).add(entry);
31 } else throw new IllegalArgumentException();
32 }
33 public void removeListener(RelationView<?> relationalKey, ITuple seed, IQueryRuntimeContextListener listener) {
34 RelationView<?> relationView = relationalKey.getWrappedKey();
35 if(view2Listeners.containsKey(relationView)) {
36 RelationUpdateListenerEntry<?> entry = new RelationUpdateListenerEntry<>(relationalKey, seed, listener);
37 view2Listeners.get(relationView).remove(entry);
38 } else throw new IllegalArgumentException();
39 }
40
41 public <D> void processChange(RelationView<D> relationView, Tuple tuple, D oldValue, D newValue) {
42 Set<RelationUpdateListenerEntry<?>> listeners = view2Listeners.get(relationView);
43 if(listeners != null) {
44 for(RelationUpdateListenerEntry<?> listener : listeners) {
45 @SuppressWarnings("unchecked")
46 RelationUpdateListenerEntry<D> typeCorrectListener = (RelationUpdateListenerEntry<D>) listener;
47 typeCorrectListener.processChange(tuple, oldValue, newValue);
48 }
49 } else throw new IllegalArgumentException("View was not indexed in constructor "+relationView);
50 }
51}
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java
new file mode 100644
index 00000000..55aed7c8
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java
@@ -0,0 +1,63 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.Arrays;
4import java.util.Objects;
5
6import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener;
7import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
8import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
9import org.eclipse.viatra.solver.data.model.Tuple;
10import org.eclipse.viatra.solver.data.query.view.RelationView;
11
12public class RelationUpdateListenerEntry<D> {
13 final RelationView<D> key;
14 final ITuple filter;
15 final IQueryRuntimeContextListener listener;
16
17 public RelationUpdateListenerEntry(RelationView<D> key, ITuple filter, IQueryRuntimeContextListener listener) {
18 super();
19 this.key = key;
20 this.filter = filter;
21 this.listener = listener;
22 }
23
24 public void processChange(Tuple tuple, D oldValue, D newValue) {
25 Object[] oldTuple = isMatching(key.getWrappedKey().transform(tuple, oldValue), filter);
26 Object[] newTuple = isMatching(key.getWrappedKey().transform(tuple, newValue), filter);
27
28 if(!Arrays.equals(oldTuple, newTuple)) {
29 if(oldTuple != null) {
30 listener.update(key, Tuples.flatTupleOf(oldTuple), false);
31 }
32 if(newTuple != null) {
33 listener.update(key, Tuples.flatTupleOf(newTuple), true);
34 }
35 }
36 }
37
38 private Object[] isMatching(Object[] tuple, ITuple filter) {
39 for(int i = 0; i<filter.getSize(); i++) {
40 final Object filterObject = filter.get(i);
41 if(filterObject != null && !filterObject.equals(tuple[i])) {
42 return null;
43 }
44 }
45 return tuple;
46 }
47
48 @Override
49 public int hashCode() {
50 return Objects.hash(filter, key, listener);
51 }
52
53 @Override
54 public boolean equals(Object obj) {
55 if (this == obj)
56 return true;
57 if (!(obj instanceof RelationUpdateListenerEntry))
58 return false;
59 RelationUpdateListenerEntry<?> other = (RelationUpdateListenerEntry<?>) obj;
60 return Objects.equals(filter, other.filter) && Objects.equals(key, other.key)
61 && Objects.equals(listener, other.listener);
62 }
63}
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java
new file mode 100644
index 00000000..01948828
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java
@@ -0,0 +1,32 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex;
4import org.eclipse.viatra.query.runtime.api.scope.IEngineContext;
5import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
6import org.eclipse.viatra.solver.data.model.Model;
7
8public class RelationalEngineContext implements IEngineContext{
9 private final IBaseIndex baseIndex = new DummyBaseIndexer();
10 private final RelationalRuntimeContext runtimeContext;
11
12
13 public RelationalEngineContext(Model model, RelationUpdateListener updateListener) {
14 runtimeContext = new RelationalRuntimeContext(model, updateListener);
15 }
16
17 @Override
18 public IBaseIndex getBaseIndex() {
19 return this.baseIndex;
20 }
21
22 @Override
23 public void dispose() {
24 //lifecycle not controlled by engine
25 }
26
27 @Override
28 public IQueryRuntimeContext getQueryRuntimeContext() {
29 return runtimeContext;
30 }
31
32}
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java
new file mode 100644
index 00000000..de500fc9
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java
@@ -0,0 +1,57 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.Collection;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.Map;
8import java.util.Set;
9
10import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContext;
11import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
12import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication;
13import org.eclipse.viatra.solver.data.query.view.RelationView;
14
15/**
16 * The meta context information for String scopes.
17 */
18public final class RelationalQueryMetaContext extends AbstractQueryMetaContext {
19
20 @Override
21 public boolean isEnumerable(IInputKey key) {
22 ensureValidKey(key);
23 return key.isEnumerable();
24 }
25
26 @Override
27 public boolean isStateless(IInputKey key) {
28 ensureValidKey(key);
29 return key instanceof RelationView<?>;
30 }
31
32 @Override
33 public Collection<InputKeyImplication> getImplications(IInputKey implyingKey) {
34 ensureValidKey(implyingKey);
35 return new HashSet<InputKeyImplication>();
36 }
37
38 @Override
39 public Map<Set<Integer>, Set<Integer>> getFunctionalDependencies(IInputKey key) {
40 ensureValidKey(key);
41 if (key instanceof RelationView) {
42 return new HashMap<Set<Integer>, Set<Integer>>();
43 } else {
44 return Collections.emptyMap();
45 }
46 }
47
48 public void ensureValidKey(IInputKey key) {
49 if (! (key instanceof RelationView<?>))
50 illegalInputKey(key);
51 }
52
53 public void illegalInputKey(IInputKey key) {
54 throw new IllegalArgumentException("The input key " + key + " is not a valid input key.");
55 }
56
57}
diff --git a/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java
new file mode 100644
index 00000000..7d1682b2
--- /dev/null
+++ b/store/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java
@@ -0,0 +1,187 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import static org.eclipse.viatra.solver.data.util.CollectionsUtil.filter;
4import static org.eclipse.viatra.solver.data.util.CollectionsUtil.map;
5
6import java.lang.reflect.InvocationTargetException;
7import java.util.Iterator;
8import java.util.Optional;
9import java.util.concurrent.Callable;
10
11import org.eclipse.viatra.query.runtime.base.core.NavigationHelperImpl;
12import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
13import org.eclipse.viatra.query.runtime.matchers.context.IQueryMetaContext;
14import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
15import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener;
16import org.eclipse.viatra.query.runtime.matchers.context.IndexingService;
17import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
18import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
19import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask;
20import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
21import org.eclipse.viatra.query.runtime.matchers.util.Accuracy;
22import org.eclipse.viatra.solver.data.model.Model;
23import org.eclipse.viatra.solver.data.query.view.RelationView;
24
25public class RelationalRuntimeContext implements IQueryRuntimeContext {
26 private final RelationalQueryMetaContext metaContext = new RelationalQueryMetaContext();
27 private final RelationUpdateListener relationUpdateListener;
28 private final Model model;
29
30 public RelationalRuntimeContext(Model model, RelationUpdateListener relationUpdateListener) {
31 this.model = model;
32 this.relationUpdateListener = relationUpdateListener;
33 }
34
35 @Override
36 public IQueryMetaContext getMetaContext() {
37 return metaContext;
38 }
39
40 //
41 /**
42 * TODO: check {@link NavigationHelperImpl#coalesceTraversals(Callable)}
43 */
44 @Override
45 public <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException {
46 try {
47 return callable.call();
48 } catch (Exception e) {
49 throw new InvocationTargetException(e);
50 }
51 }
52
53 @Override
54 public boolean isCoalescing() {
55 return true;
56 }
57
58 @Override
59 public boolean isIndexed(IInputKey key, IndexingService service) {
60 if(key instanceof RelationView<?>) {
61 RelationView<?> relationalKey = (RelationView<?>) key;
62 return this.relationUpdateListener.containsRelationalView(relationalKey);
63 } else {
64 return false;
65 }
66 }
67
68 @Override
69 public void ensureIndexed(IInputKey key, IndexingService service) {
70 if(!isIndexed(key, service)) {
71 throw new IllegalStateException("Engine tries to index a new key " +key);
72 }
73 }
74
75 RelationView<?> checkKey(IInputKey key) {
76 if(key instanceof RelationView) {
77 RelationView<?> relationViewKey = (RelationView<?>) key;
78 if(relationUpdateListener.containsRelationalView(relationViewKey)) {
79 return relationViewKey;
80 } else {
81 throw new IllegalStateException("Query is asking for non-indexed key");
82 }
83 } else {
84 throw new IllegalStateException("Query is asking for non-relational key");
85 }
86 }
87
88 @Override
89 public int countTuples(IInputKey key, TupleMask seedMask, ITuple seed) {
90 RelationView<?> relationalViewKey = checkKey(key);
91 Iterable<Object[]> allObjects = relationalViewKey.getAll(model);
92 Iterable<Object[]> filteredBySeed = filter(allObjects,objectArray -> isMatching(objectArray,seedMask,seed));
93 Iterator<Object[]> iterator = filteredBySeed.iterator();
94 int result = 0;
95 while(iterator.hasNext()) {
96 iterator.next();
97 result++;
98 }
99 return result;
100 }
101
102 @Override
103 public Optional<Long> estimateCardinality(IInputKey key, TupleMask groupMask, Accuracy requiredAccuracy) {
104 return Optional.empty();
105 }
106
107 @Override
108 public Iterable<Tuple> enumerateTuples(IInputKey key, TupleMask seedMask, ITuple seed) {
109 RelationView<?> relationalViewKey = checkKey(key);
110 Iterable<Object[]> allObjects = relationalViewKey.getAll(model);
111 Iterable<Object[]> filteredBySeed = filter(allObjects,objectArray -> isMatching(objectArray,seedMask,seed));
112 return map(filteredBySeed,Tuples::flatTupleOf);
113 }
114
115 private boolean isMatching(Object[] tuple, TupleMask seedMask, ITuple seed) {
116 for(int i=0; i<seedMask.indices.length; i++) {
117 final Object seedElement = seed.get(i);
118 final Object tupleElement = tuple[seedMask.indices[i]];
119 if(!tupleElement.equals(seedElement)) {
120 return false;
121 }
122 }
123 return true;
124 }
125// private Object[] toObjectMask(RelationViewKey<?> relationalViewKey, TupleMask seedMask, ITuple seed) {
126// final int arity = relationalViewKey.getArity();
127// Object[] result = new Object[arity];
128// for(int i = 0; i<seedMask.indices.length; i++) {
129// result[seedMask.indices[i]] = seed.get(i);
130// }
131// return result;
132// }
133
134 @Override
135 public Iterable<? extends Object> enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed) {
136 return enumerateTuples(key, seedMask, seed);
137 }
138
139 @Override
140 public boolean containsTuple(IInputKey key, ITuple seed) {
141 RelationView<?> relationalViewKey = checkKey(key);
142 return relationalViewKey.get(model,seed.getElements());
143 }
144
145 @Override
146 public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) {
147 RelationView<?> relationalKey = checkKey(key);
148 this.relationUpdateListener.addListener(relationalKey, seed, listener);
149
150 }
151
152 @Override
153 public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) {
154 RelationView<?> relationalKey = checkKey(key);
155 this.relationUpdateListener.removeListener(relationalKey, seed, listener);
156 }
157
158 @Override
159 public Object wrapElement(Object externalElement) {
160 return externalElement;
161 }
162
163 @Override
164 public Object unwrapElement(Object internalElement) {
165 return internalElement;
166 }
167
168 @Override
169 public Tuple wrapTuple(Tuple externalElements) {
170 return externalElements;
171 }
172
173 @Override
174 public Tuple unwrapTuple(Tuple internalElements) {
175 return internalElements;
176 }
177
178 @Override
179 public void ensureWildcardIndexing(IndexingService service) {
180 throw new UnsupportedOperationException();
181 }
182
183 @Override
184 public void executeAfterTraversal(Runnable runnable) throws InvocationTargetException {
185 runnable.run();
186 }
187}