aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/AdvancedViatraQueryEngine.java
diff options
context:
space:
mode:
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.java363
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 *******************************************************************************/
9package tools.refinery.viatra.runtime.api;
10
11import tools.refinery.viatra.runtime.api.scope.QueryScope;
12import tools.refinery.viatra.runtime.internal.apiimpl.ViatraQueryEngineImpl;
13import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException;
14import tools.refinery.viatra.runtime.matchers.backend.*;
15
16import java.lang.reflect.InvocationTargetException;
17import 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 */
47public 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}