aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/IQueryRuntimeContext.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/IQueryRuntimeContext.java')
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/IQueryRuntimeContext.java287
1 files changed, 287 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/IQueryRuntimeContext.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/IQueryRuntimeContext.java
new file mode 100644
index 00000000..61359c1b
--- /dev/null
+++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/matchers/context/IQueryRuntimeContext.java
@@ -0,0 +1,287 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, 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 *
8 * SPDX-License-Identifier: EPL-2.0
9 *******************************************************************************/
10package tools.refinery.viatra.runtime.matchers.context;
11
12import tools.refinery.viatra.runtime.CancellationToken;
13import tools.refinery.viatra.runtime.matchers.planning.helpers.StatisticsHelper;
14import tools.refinery.viatra.runtime.matchers.tuple.ITuple;
15import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
16import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
17import tools.refinery.viatra.runtime.matchers.util.Accuracy;
18
19import java.lang.reflect.InvocationTargetException;
20import java.util.Optional;
21import java.util.concurrent.Callable;
22
23/**
24 * Provides instance model information (relations corresponding to input keys) to query evaluator backends at runtime.
25 * Implementors shall extend {@link AbstractQueryRuntimeContext} instead directly this interface.
26 *
27 * @author Bergmann Gabor
28 * @noimplement This interface is not intended to be implemented by clients. Extend {@link AbstractQueryRuntimeContext} instead.
29 */
30public interface IQueryRuntimeContext {
31 /**
32 * Provides metamodel-specific info independent of the runtime instance model.
33 */
34 public IQueryMetaContext getMetaContext();
35
36
37 /**
38 * The given callable will be executed, and all model traversals will be delayed until the execution is done. If
39 * there are any outstanding information to be read from the model, a single coalesced model traversal will
40 * initialize the caches and deliver the notifications.
41 *
42 * <p> Calls may be nested. A single coalesced traversal will happen at the end of the outermost call.
43 *
44 * <p> <b>Caution: </b> results returned by the runtime context may be incomplete during the coalescing period, to be corrected by notifications sent during the final coalesced traversal.
45 * For example, if a certain input key is not cached yet, an empty relation may be reported during <code>callable.call()</code>; the cache will be constructed after the call terminates and notifications will deliver the entire content of the relation.
46 * Non-incremental query backends should therefore never enumerate input keys while coalesced (verify using {@link #isCoalescing()}).
47 *
48 * @param callable
49 */
50 public abstract <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException;
51 /**
52 * @return true iff currently within a coalescing section (i.e. within the callable of a call to {@link #coalesceTraversals(Callable)}).
53 */
54 public boolean isCoalescing();
55
56 /**
57 * Returns true if index is available for the given key providing the given service.
58 * @throws IllegalArgumentException if key is not enumerable or an unknown type, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
59 * @since 1.4
60 */
61 public boolean isIndexed(IInputKey key, IndexingService service);
62
63 /**
64 * If the given (enumerable) input key is not yet indexed, the model will be traversed
65 * (after the end of the outermost coalescing block, see {@link IQueryRuntimeContext#coalesceTraversals(Callable)})
66 * so that the index can be built. It is possible that the base indexer will select a higher indexing level merging
67 * multiple indexing requests to an appropriate level.
68 *
69 * <p><b>Postcondition:</b> After invoking this method, {@link #getIndexed(IInputKey, IndexingService)} for the same key
70 * and service will be guaranteed to return the requested or a highing indexing level as soon as {@link #isCoalescing()} first returns false.
71 *
72 * <p><b>Precondition:</b> the given key is enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
73 * @throws IllegalArgumentException if key is not enumerable or an unknown type, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
74 * @since 1.4
75 */
76 public void ensureIndexed(IInputKey key, IndexingService service);
77
78 /**
79 * Returns the number of tuples in the extensional relation identified by the input key seeded with the given mask and tuple.
80 *
81 * @param key an input key
82 * @param seedMask
83 * a mask that extracts those parameters of the input key (from the entire parameter list) that should be
84 * bound to a fixed value; must not be null. <strong>Note</strong>: any given index must occur at most once in seedMask.
85 * @param seed
86 * the tuple of fixed values restricting the match set to be considered, in the same order as given in
87 * parameterSeedMask, so that for each considered match tuple,
88 * projectedParameterSeed.equals(parameterSeedMask.transform(match)) should hold. Must not be null.
89 *
90 * @return the number of tuples in the model for the given key and seed
91 *
92 * <p><b>Precondition:</b> the given key is enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
93 * @throws IllegalArgumentException if key is not enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
94 * @since 1.7
95 */
96 public int countTuples(IInputKey key, TupleMask seedMask, ITuple seed);
97
98
99 /**
100 * Gives an estimate of the number of different groups the tuples of the given relation are projected into by the given mask
101 * (e.g. for an identity mask, this means the full relation size). The estimate must meet the required accuracy.
102 *
103 * <p> Must accept any input key, even non-enumerables or those not recognized by this runtime context.
104 * If there is insufficient information to provide an answer up to the required precision, {@link Optional#empty()} is returned.
105 *
106 * <p> PRE: {@link TupleMask#isNonrepeating()} must hold for the group mask.
107 *
108 * @return if available, an estimate of the cardinality of the projection of the given extensional relation, with the desired accuracy.
109 *
110 * @since 2.1
111 */
112 public Optional<Long> estimateCardinality(IInputKey key, TupleMask groupMask, Accuracy requiredAccuracy);
113
114
115 /**
116 * Gives an estimate of the average size of different groups the tuples of the given relation are projected into by the given mask
117 * (e.g. for an identity mask, this means 1, while for an empty mask, the result is the full relation size).
118 * The estimate must meet the required accuracy.
119 *
120 * <p> Must accept any input key, even non-enumerables or those not recognized by this runtime context.
121 * If there is insufficient information to provide an answer up to the required precision, {@link Optional#empty()} may be returned.
122 *
123 * <p> For an empty relation, zero is acceptable as an exact answer.
124 *
125 * <p> PRE: {@link TupleMask#isNonrepeating()} must hold for the group mask.
126 *
127 * @return if available, an estimate of the average size of each projection group of the given extensional relation, with the desired accuracy.
128 *
129 * @since 2.1
130 */
131 public default Optional<Double> estimateAverageBucketSize(IInputKey key, TupleMask groupMask, Accuracy requiredAccuracy) {
132 if (key.isEnumerable()) {
133 return StatisticsHelper.estimateAverageBucketSize(groupMask, requiredAccuracy,
134 (mask, accuracy) -> this.estimateCardinality(key, mask, accuracy));
135 } else return groupMask.isIdentity() ? Optional.of(1.0) : Optional.empty();
136 }
137
138
139 /**
140 * Returns the tuples in the extensional relation identified by the input key, optionally seeded with the given tuple.
141 *
142 * @param key an input key
143 * @param seedMask
144 * a mask that extracts those parameters of the input key (from the entire parameter list) that should be
145 * bound to a fixed value; must not be null. <strong>Note</strong>: any given index must occur at most once in seedMask.
146 * @param seed
147 * the tuple of fixed values restricting the match set to be considered, in the same order as given in
148 * parameterSeedMask, so that for each considered match tuple,
149 * projectedParameterSeed.equals(parameterSeedMask.transform(match)) should hold. Must not be null.
150 * @return the tuples in the model for the given key and seed
151 *
152 * <p><b>Precondition:</b> the given key is enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
153 * @throws IllegalArgumentException if key is not enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
154 * @since 1.7
155 */
156 public Iterable<Tuple> enumerateTuples(IInputKey key, TupleMask seedMask, ITuple seed);
157
158 /**
159 * Simpler form of {@link #enumerateTuples(IInputKey, TupleMask, Tuple)} in the case where all values of the tuples
160 * are bound by the seed except for one.
161 *
162 * <p>
163 * Selects the tuples in the extensional relation identified by the input key, optionally seeded with the given
164 * tuple, and then returns the single value from each tuple which is not bound by the ssed mask.
165 *
166 * @param key
167 * an input key
168 * @param seedMask
169 * a mask that extracts those parameters of the input key (from the entire parameter list) that should be
170 * bound to a fixed value; must not be null. <strong>Note</strong>: any given index must occur at most
171 * once in seedMask, and seedMask must include all parameters in any arbitrary order except one.
172 * @param seed
173 * the tuple of fixed values restricting the match set to be considered, in the same order as given in
174 * parameterSeedMask, so that for each considered match tuple,
175 * projectedParameterSeed.equals(parameterSeedMask.transform(match)) should hold. Must not be null.
176 * @return the objects in the model for the given key and seed
177 *
178 * <p>
179 * <b>Precondition:</b> the given key is enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
180 * @throws IllegalArgumentException
181 * if key is not enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
182 * @since 1.7
183 */
184 public Iterable<? extends Object> enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed);
185
186 /**
187 * Simpler form of {@link #enumerateTuples(IInputKey, TupleMask, Tuple)} in the case where all values of the tuples
188 * are bound by the seed.
189 *
190 * <p>
191 * Returns whether the given tuple is in the extensional relation identified by the input key.
192 *
193 * <p>
194 * Note: this call works for non-enumerable input keys as well.
195 *
196 * @param key
197 * an input key
198 * @param seed
199 * the tuple of fixed values restricting the match set to be considered, in the same order as given in
200 * parameterSeedMask, so that for each considered match tuple,
201 * projectedParameterSeed.equals(parameterSeedMask.transform(match)) should hold. Must not be null.
202 * @return true iff there is at least a single tuple contained in the relation that corresponds to the seed tuple
203 * @since 2.0
204 */
205 public boolean containsTuple(IInputKey key, ITuple seed);
206
207
208 /**
209 * Subscribes for updates in the extensional relation identified by the input key, optionally seeded with the given tuple.
210 * <p> This should be called after invoking
211 *
212 * @param key an input key
213 * @param seed can be null or a tuple with matching arity;
214 * if non-null, only those updates in the model are notified about
215 * that match the seed at positions where the seed is non-null.
216 * @param listener will be notified of future changes
217 *
218 * <p><b>Precondition:</b> the given key is enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
219 * @throws IllegalArgumentException if key is not enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
220 */
221 public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener);
222
223 /**
224 * Unsubscribes from updates in the extensional relation identified by the input key, optionally seeded with the given tuple.
225 *
226 * @param key an input key
227 * @param seed can be null or a tuple with matching arity;
228 * if non-null, only those updates in the model are notified about
229 * that match the seed at positions where the seed is non-null.
230 * @param listener will no longer be notified of future changes
231 *
232 * <p><b>Precondition:</b> the given key is enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
233 * @throws IllegalArgumentException if key is not enumerable, see {@link IQueryMetaContext#isEnumerable(IInputKey)}.
234 */
235 public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener);
236 /*
237 TODO: uniqueness
238 */
239
240 /**
241 * Wraps the external element into the internal representation that is to be used by the query backend
242 * <p> model element -> internal object.
243 * <p> null must be mapped to null.
244 */
245 public Object wrapElement(Object externalElement);
246
247 /**
248 * Unwraps the internal representation of the element into its original form
249 * <p> internal object -> model element
250 * <p> null must be mapped to null.
251 */
252 public Object unwrapElement(Object internalElement);
253
254 /**
255 * Unwraps the tuple of elements into the internal representation that is to be used by the query backend
256 * <p> model elements -> internal objects
257 * <p> null must be mapped to null.
258 */
259 public Tuple wrapTuple(Tuple externalElements);
260
261 /**
262 * Unwraps the tuple of internal representations of elements into their original forms
263 * <p> internal objects -> model elements
264 * <p> null must be mapped to null.
265 */
266 public Tuple unwrapTuple(Tuple internalElements);
267
268 /**
269 * Starts wildcard indexing for the given service. After this call, no registration is required for this {@link IndexingService}.
270 * a previously set wildcard level cannot be lowered, only extended.
271 * @since 1.4
272 */
273 public void ensureWildcardIndexing(IndexingService service);
274
275 /**
276 * Execute the given runnable after traversal. It is guaranteed that the runnable is executed as soon as
277 * the indexing is finished. The callback is executed only once, then is removed from the callback queue.
278 * @param traversalCallback
279 * @throws InvocationTargetException
280 * @since 1.4
281 */
282 public void executeAfterTraversal(Runnable runnable) throws InvocationTargetException;
283
284 default CancellationToken getCancellationToken() {
285 return CancellationToken.NONE;
286 }
287}