diff options
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java')
-rw-r--r-- | subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java new file mode 100644 index 00000000..32a3430d --- /dev/null +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java | |||
@@ -0,0 +1,363 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2013, Bergmann Gabor, Istvan Rath and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.api; | ||
10 | |||
11 | import tools.refinery.viatra.runtime.api.scope.QueryScope; | ||
12 | import tools.refinery.viatra.runtime.internal.apiimpl.ViatraQueryEngineImpl; | ||
13 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | ||
14 | import tools.refinery.viatra.runtime.matchers.backend.*; | ||
15 | |||
16 | import java.lang.reflect.InvocationTargetException; | ||
17 | import java.util.concurrent.Callable; | ||
18 | |||
19 | /** | ||
20 | * Advanced interface to a VIATRA incremental evaluation engine. | ||
21 | * | ||
22 | * <p> | ||
23 | * You can create a new, private, unmanaged {@link AdvancedViatraQueryEngine} instance using | ||
24 | * {@link #createUnmanagedEngine(QueryScope)}. Additionally, you can access the advanced interface on any | ||
25 | * {@link ViatraQueryEngine} by {@link AdvancedViatraQueryEngine#from(ViatraQueryEngine)}. | ||
26 | * | ||
27 | * <p> | ||
28 | * While the default interface {@link ViatraQueryEngine}, is suitable for most users, this advanced interface provides more | ||
29 | * control over the engine. The most important added functionality is the following: | ||
30 | * <ul> | ||
31 | * <li>You can have tighter control over the lifecycle of the engine, if you create a private, unmanaged engine | ||
32 | * instance. For instance, a (non-managed) engine can be disposed in order to detach from the EMF model and stop | ||
33 | * listening on update notifications. The indexes built previously in the engine can then be garbage collected, even if | ||
34 | * the model itself is retained. Total lifecycle control is only available for private, unmanaged engines (created using | ||
35 | * {@link #createUnmanagedEngine(QueryScope)}); a managed engine (obtained via {@link ViatraQueryEngine#on(QueryScope)}) is | ||
36 | * shared among clients and can not be disposed or wiped. | ||
37 | * <li>You can add and remove listeners to receive notification when the model or the match sets change. | ||
38 | * <li>You can add and remove listeners to receive notification on engine lifecycle events, such as creation of new | ||
39 | * matchers. For instance, if you explicitly share a private, unmanaged engine between multiple sites, you should | ||
40 | * register a callback using {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client | ||
41 | * has called the destructive methods {@link #dispose()} or {@link #wipe()}. | ||
42 | * </ul> | ||
43 | * | ||
44 | * @author Bergmann Gabor | ||
45 | * @noextend This class is not intended to be subclassed by clients. | ||
46 | */ | ||
47 | public abstract class AdvancedViatraQueryEngine extends ViatraQueryEngine { | ||
48 | |||
49 | /** | ||
50 | * Creates a new unmanaged VIATRA Query engine to evaluate queries over a given scope specified by an {@link QueryScope}. | ||
51 | * | ||
52 | * <p> Repeated invocations will return different instances, so other clients are unable to independently access | ||
53 | * and influence the returned engine. Note that unmanaged engines do not benefit from some performance improvements | ||
54 | * that stem from sharing incrementally maintained indices and caches between multiple clients using the same managed | ||
55 | * engine instance. | ||
56 | * | ||
57 | * <p> | ||
58 | * Client is responsible for the lifecycle of the returned engine, hence the usage of the advanced interface | ||
59 | * {@link AdvancedViatraQueryEngine}. | ||
60 | * | ||
61 | * <p> | ||
62 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. | ||
63 | * | ||
64 | * @param scope | ||
65 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. | ||
66 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. | ||
67 | * @return the advanced interface to a newly created unmanaged engine | ||
68 | * @since 0.9 | ||
69 | */ | ||
70 | public static AdvancedViatraQueryEngine createUnmanagedEngine(QueryScope scope) { | ||
71 | return new ViatraQueryEngineImpl(null, scope); | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * Creates a new unmanaged VIATRA Query engine to evaluate queries over a given scope specified by an {@link QueryScope}. | ||
76 | * | ||
77 | * <p> Repeated invocations will return different instances, so other clients are unable to independently access | ||
78 | * and influence the returned engine. Note that unmanaged engines do not benefit from some performance improvements | ||
79 | * that stem from sharing incrementally maintained indices and caches between multiple clients using the same managed | ||
80 | * engine instance. | ||
81 | * | ||
82 | * <p> | ||
83 | * Client is responsible for the lifecycle of the returned engine, hence the usage of the advanced interface | ||
84 | * {@link AdvancedViatraQueryEngine}. | ||
85 | * | ||
86 | * <p> | ||
87 | * The match set of any patterns will be incrementally refreshed upon updates from this scope. | ||
88 | * | ||
89 | * @param scope | ||
90 | * the scope of query evaluation; the definition of the set of model elements that this engine is operates on. | ||
91 | * Provide e.g. a {@link EMFScope} for evaluating queries on an EMF model. | ||
92 | * @return the advanced interface to a newly created unmanaged engine | ||
93 | * @since 1.4 | ||
94 | */ | ||
95 | public static AdvancedViatraQueryEngine createUnmanagedEngine(QueryScope scope, ViatraQueryEngineOptions options) { | ||
96 | return new ViatraQueryEngineImpl(null, scope, options); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Provides access to a given existing engine through the advanced interface. | ||
101 | * | ||
102 | * <p> | ||
103 | * Caveat: if the referenced engine is managed (i.e. created via {@link ViatraQueryEngine#on(QueryScope)}), the advanced | ||
104 | * methods {@link #dispose()} and {@link #wipe()} will not be allowed. | ||
105 | * | ||
106 | * @param engine | ||
107 | * the engine to access using the advanced interface | ||
108 | * @return a reference to the same engine conforming to the advanced interface | ||
109 | */ | ||
110 | public static AdvancedViatraQueryEngine from(ViatraQueryEngine engine) { | ||
111 | return (AdvancedViatraQueryEngine) engine; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * Add an engine lifecycle listener to this engine instance. | ||
116 | * | ||
117 | * @param listener | ||
118 | * the {@link ViatraQueryEngineLifecycleListener} that should listen to lifecycle events from this engine | ||
119 | */ | ||
120 | public abstract void addLifecycleListener(ViatraQueryEngineLifecycleListener listener); | ||
121 | |||
122 | /** | ||
123 | * Remove an existing lifecycle listener from this engine instance. | ||
124 | * | ||
125 | * @param listener | ||
126 | * the {@link ViatraQueryEngineLifecycleListener} that should not listen to lifecycle events from this | ||
127 | * engine anymore | ||
128 | */ | ||
129 | public abstract void removeLifecycleListener(ViatraQueryEngineLifecycleListener listener); | ||
130 | |||
131 | /** | ||
132 | * Add an model update event listener to this engine instance (that fires its callbacks according to its | ||
133 | * notification level). | ||
134 | * | ||
135 | * @param listener | ||
136 | * the {@link ViatraQueryModelUpdateListener} that should listen to model update events from this engine. | ||
137 | */ | ||
138 | public abstract void addModelUpdateListener(ViatraQueryModelUpdateListener listener); | ||
139 | |||
140 | /** | ||
141 | * Remove an existing model update event listener to this engine instance. | ||
142 | * | ||
143 | * @param listener | ||
144 | * the {@link ViatraQueryModelUpdateListener} that should not listen to model update events from this engine | ||
145 | * anymore | ||
146 | */ | ||
147 | public abstract void removeModelUpdateListener(ViatraQueryModelUpdateListener listener); | ||
148 | |||
149 | /** | ||
150 | * Registers low-level callbacks for match appearance and disappearance on this pattern matcher. | ||
151 | * | ||
152 | * <p> | ||
153 | * <b>Caution: </b> This is a low-level callback that is invoked when the pattern matcher is not necessarily in a | ||
154 | * consistent state yet. Importantly, no model modification permitted during the callback. Most users should use the | ||
155 | * databinding support ({@link org.eclipse.viatra.addon.databinding.runtime.api.ViatraObservables ViatraObservables}) or the event-driven API | ||
156 | * ({@link org.eclipse.viatra.transformation.evm.api.EventDrivenVM EventDrivenVM}) instead. | ||
157 | * | ||
158 | * <p> | ||
159 | * Performance note: expected to be much more efficient than polling at {@link #addCallbackAfterUpdates(Runnable)}, | ||
160 | * but prone to "signal hazards", e.g. spurious match appearances that will disappear immediately afterwards. | ||
161 | * | ||
162 | * <p> | ||
163 | * The callback can be unregistered via {@link #removeCallbackOnMatchUpdate(IMatchUpdateListener)}. | ||
164 | * | ||
165 | * @param fireNow | ||
166 | * if true, appearCallback will be immediately invoked on all current matches as a one-time effect. See | ||
167 | * also {@link ViatraQueryMatcher#forEachMatch(IMatchProcessor)}. | ||
168 | * @param listener | ||
169 | * the listener that will be notified of each new match that appears or disappears, starting from now. | ||
170 | * @param matcher | ||
171 | * the {@link ViatraQueryMatcher} for which this listener should be active | ||
172 | */ | ||
173 | public abstract <Match extends IPatternMatch> void addMatchUpdateListener(ViatraQueryMatcher<Match> matcher, | ||
174 | IMatchUpdateListener<? super Match> listener, boolean fireNow); | ||
175 | |||
176 | /** | ||
177 | * Remove an existing match update event listener to this engine instance. | ||
178 | * | ||
179 | * @param matcher | ||
180 | * the {@link ViatraQueryMatcher} for which this listener should not be active anymore | ||
181 | * @param listener | ||
182 | * the {@link IMatchUpdateListener} that should not receive the callbacks anymore | ||
183 | */ | ||
184 | public abstract <Match extends IPatternMatch> void removeMatchUpdateListener(ViatraQueryMatcher<Match> matcher, | ||
185 | IMatchUpdateListener<? super Match> listener); | ||
186 | |||
187 | |||
188 | /** | ||
189 | * Access a pattern matcher based on a {@link IQuerySpecification}, overriding some of the default query evaluation hints. | ||
190 | * Multiple calls may return the same matcher depending on the actual evaluation hints. | ||
191 | * | ||
192 | * <p> It is guaranteed that this method will always return a matcher instance which is functionally compatible | ||
193 | * with the requested functionality (see {@link IMatcherCapability}). | ||
194 | * Otherwise, the query evaluator is free to ignore any hints. | ||
195 | * | ||
196 | * <p> For stateful query backends (Rete), hints may be effective only the first time a matcher is created. | ||
197 | * @param querySpecification a {@link IQuerySpecification} that describes a VIATRA query | ||
198 | * @return a pattern matcher corresponding to the specification | ||
199 | * @param optionalEvaluationHints additional / overriding options on query evaluation; passing null means default options associated with the query | ||
200 | * @throws ViatraQueryRuntimeException if the matcher could not be initialized | ||
201 | * @since 0.9 | ||
202 | */ | ||
203 | public abstract <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getMatcher( | ||
204 | IQuerySpecification<Matcher> querySpecification, | ||
205 | QueryEvaluationHint optionalEvaluationHints); | ||
206 | |||
207 | /** | ||
208 | * Initializes matchers for a group of patterns as one step (optionally overriding some of the default query evaluation hints). | ||
209 | * If some of the pattern matchers are already | ||
210 | * constructed in the engine, no task is performed for them. | ||
211 | * | ||
212 | * <p> | ||
213 | * This preparation step has the advantage that it prepares pattern matchers for an arbitrary number of patterns in a | ||
214 | * single-pass traversal of the model. | ||
215 | * This is typically more efficient than traversing the model each time an individual pattern matcher is initialized on demand. | ||
216 | * The performance benefit only manifests itself if the engine is not in wildcard mode. | ||
217 | * | ||
218 | * @param queryGroup a {@link IQueryGroup} identifying a set of VIATRA queries | ||
219 | * @param optionalEvaluationHints additional / overriding options on query evaluation; passing null means default options associated with each query | ||
220 | * @throws ViatraQueryRuntimeException | ||
221 | * if there was an error in preparing the engine | ||
222 | * @since 0.9 | ||
223 | */ | ||
224 | public abstract void prepareGroup(IQueryGroup queryGroup, QueryEvaluationHint optionalEvaluationHints); | ||
225 | |||
226 | /** | ||
227 | * Indicates whether the engine is managed, i.e. the default engine assigned to the given scope root by | ||
228 | * {@link ViatraQueryEngine#on(QueryScope)}. | ||
229 | * | ||
230 | * <p> | ||
231 | * If the engine is managed, there may be other clients using it, as all calls to | ||
232 | * {@link ViatraQueryEngine#on(QueryScope)} return the same managed engine instance for a given scope root. Therefore the | ||
233 | * destructive methods {@link #wipe()} and {@link #dispose()} are not allowed. | ||
234 | * | ||
235 | * <p> | ||
236 | * On the other hand, if the engine is unmanaged (i.e. a private instance created using | ||
237 | * {@link #createUnmanagedEngine(QueryScope)}), then {@link #wipe()} and {@link #dispose()} can be called. If you | ||
238 | * explicitly share a private, unmanaged engine between multiple sites, register a callback using | ||
239 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called these | ||
240 | * destructive methods. | ||
241 | * | ||
242 | * @return true if the engine is managed, and therefore potentially shared with other clients querying the same EMF | ||
243 | * model | ||
244 | */ | ||
245 | public abstract boolean isManaged(); | ||
246 | |||
247 | /** | ||
248 | * Indicates whether the engine is in a tainted, inconsistent state due to some internal errors. If true, results | ||
249 | * are no longer reliable; engine should be disposed. | ||
250 | * | ||
251 | * <p> | ||
252 | * The engine is in a tainted state if any of its internal processes report back a fatal error. The | ||
253 | * {@link ViatraQueryEngineLifecycleListener} interface provides a callback method for entering the tainted state. | ||
254 | * | ||
255 | * @return the tainted state | ||
256 | */ | ||
257 | public abstract boolean isTainted(); | ||
258 | |||
259 | /** | ||
260 | * Discards any pattern matcher caches and forgets known patterns. The base index built directly on the underlying | ||
261 | * EMF model, however, is kept in memory to allow reuse when new pattern matchers are built. Use this method if you | ||
262 | * have e.g. new versions of the same patterns, to be matched on the same model. | ||
263 | * | ||
264 | * <p> | ||
265 | * Matcher objects will continue to return stale results. If no references are retained to the matchers, they can | ||
266 | * eventually be GC'ed. | ||
267 | * <p> | ||
268 | * Disallowed if the engine is managed (see {@link #isManaged()}), as there may be other clients using it. | ||
269 | * <p> | ||
270 | * If you explicitly share a private, unmanaged engine between multiple sites, register a callback using | ||
271 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called this | ||
272 | * destructive method. | ||
273 | * | ||
274 | * @throws UnsupportedOperationException | ||
275 | * if engine is managed | ||
276 | */ | ||
277 | public abstract void wipe(); | ||
278 | |||
279 | /** | ||
280 | * Completely disconnects and dismantles the engine. Cannot be reversed. | ||
281 | * <p> | ||
282 | * Matcher objects will continue to return stale results. If no references are retained to the matchers or the | ||
283 | * engine, they can eventually be GC'ed, and they won't block the EMF model from being GC'ed anymore. | ||
284 | * <p> | ||
285 | * The base indexer (see {@link #getBaseIndex()}) built on the model will be disposed alongside the engine, unless | ||
286 | * the user has manually added listeners on the base index that were not removed yet. | ||
287 | * <p> | ||
288 | * Disallowed if the engine is managed (see {@link #isManaged()}), as there may be other clients using it. | ||
289 | * <p> | ||
290 | * If you explicitly share a private, unmanaged engine between multiple sites, register a callback using | ||
291 | * {@link #addLifecycleListener(ViatraQueryEngineLifecycleListener)} to learn when another client has called this | ||
292 | * destructive method. | ||
293 | * | ||
294 | * @throws UnsupportedOperationException | ||
295 | * if engine is managed | ||
296 | */ | ||
297 | public abstract void dispose(); | ||
298 | |||
299 | /** | ||
300 | * Provides access to the selected query backend component of the VIATRA Query engine. | ||
301 | * @noreference for internal use only | ||
302 | * @throws ViatraQueryRuntimeException | ||
303 | */ | ||
304 | public abstract IQueryBackend getQueryBackend(IQueryBackendFactory iQueryBackendFactory); | ||
305 | |||
306 | /** | ||
307 | * Access an existing pattern matcher based on a {@link IQuerySpecification}, and optional hints override. | ||
308 | * @param querySpecification a {@link IQuerySpecification} that describes a VIATRA query specification | ||
309 | * @param optionalOverrideHints a {@link QueryEvaluationHint} that may override the pattern hints (can be null) | ||
310 | * @return a pattern matcher corresponding to the specification, <code>null</code> if a matcher does not exist yet. | ||
311 | * @since 1.4 | ||
312 | */ | ||
313 | public abstract <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getExistingMatcher(IQuerySpecification<Matcher> querySpecification, QueryEvaluationHint optionalOverrideHints); | ||
314 | |||
315 | /** | ||
316 | * Returns the immutable {@link ViatraQueryEngineOptions} of the engine. | ||
317 | * | ||
318 | * @return the engine options | ||
319 | * @since 1.4 | ||
320 | */ | ||
321 | public abstract ViatraQueryEngineOptions getEngineOptions(); | ||
322 | |||
323 | /** | ||
324 | * Return the underlying result provider for the given matcher. | ||
325 | * | ||
326 | * @beta This method may change in future versions | ||
327 | * @since 1.4 | ||
328 | * @noreference This method is considered internal API | ||
329 | */ | ||
330 | public abstract IQueryResultProvider getResultProviderOfMatcher(ViatraQueryMatcher<? extends IPatternMatch> matcher); | ||
331 | |||
332 | /** | ||
333 | * The given callable will be executed, and all update propagation in stateful query backends | ||
334 | * will be delayed until the execution is done. Within the callback, these backends will provide stale results. | ||
335 | * | ||
336 | * <p> It is optional for a {@link IQueryBackend} to support the delaying of update propagation; stateless backends will display up-to-date results. | ||
337 | * In this case, the given callable shall be executed, and the update propagation shall happen just like in non-delayed execution. | ||
338 | * | ||
339 | * <p> Example: in the Rete network, no messages will be propagated until the given callable is executed. | ||
340 | * After the execution of the callable, all accumulated messages will be delivered. | ||
341 | * | ||
342 | * <p> The purpose of this method is that stateful query backends may save work when multiple model modifications are performed within the callback that partially cancel each other out. | ||
343 | * | ||
344 | * @param callable the callable to be executed | ||
345 | * @return the result of the callable | ||
346 | * @since 1.6 | ||
347 | */ | ||
348 | public abstract <V> V delayUpdatePropagation(Callable<V> callable) throws InvocationTargetException; | ||
349 | |||
350 | /** | ||
351 | * Returns true if the update propagation in this engine is currently delayed, false otherwise. | ||
352 | * | ||
353 | * @see {@link #delayUpdatePropagation(Callable)} | ||
354 | * @since 1.6 | ||
355 | */ | ||
356 | public abstract boolean isUpdatePropagationDelayed(); | ||
357 | |||
358 | /** | ||
359 | * Returns true if the {@link #dispose()} method was called on this engine previously. | ||
360 | * @since 2.0 | ||
361 | */ | ||
362 | public abstract boolean isDisposed(); | ||
363 | } | ||