diff options
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.java | 287 |
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 | *******************************************************************************/ | ||
10 | package tools.refinery.viatra.runtime.matchers.context; | ||
11 | |||
12 | import tools.refinery.viatra.runtime.CancellationToken; | ||
13 | import tools.refinery.viatra.runtime.matchers.planning.helpers.StatisticsHelper; | ||
14 | import tools.refinery.viatra.runtime.matchers.tuple.ITuple; | ||
15 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
16 | import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; | ||
17 | import tools.refinery.viatra.runtime.matchers.util.Accuracy; | ||
18 | |||
19 | import java.lang.reflect.InvocationTargetException; | ||
20 | import java.util.Optional; | ||
21 | import 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 | */ | ||
30 | public 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 | } | ||