blob: 77c3dacceb10b4dae274bf9a106f7589f0a89fd7 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-language" content="en">
<meta name="description" content="Scalable Reactive Model Transformations">
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="/viatra/js/googleAnalytics.js"></script>
<script type="text/javascript" src="/viatra/js/magnific-popup.video.js"></script>
<script type="text/javascript" src="/viatra/js/magnific-popup.min.js"></script>
<script type="text/javascript" src="/viatra/js/functions.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="/viatra/angular/viatra.js"></script>
<script src="/viatra/highlight.js/highlight.min.js"></script>
<link rel="stylesheet" type="text/css" href="//www.eclipse.org/eclipse.org-common/themes/solstice/public/stylesheets/vendor/cookieconsent/cookieconsent.min.css" />
<script src="//www.eclipse.org/eclipse.org-common/themes/solstice/public/javascript/vendor/cookieconsent/default.min.js"></script>
<link rel="shortcut icon" type="image/x-icon" href="/viatra/favicon.ico" />
<title>Viatra - Scalable reactive model transformations</title>
<link type="text/css" rel="stylesheet" href="/viatra/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="/viatra/css/style.css" />
<link type="text/css" rel="stylesheet" href="/viatra/css/media.css" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300italic,700,300' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://use.fontawesome.com/ef6567f233.css">
<link rel="stylesheet" href="/viatra/highlight.js/styles/foundation.min.css">
<link rel="stylesheet" type="text/css" href="/viatra/css/asciidoctor.css"/>
</head>
<body ng-app="viatra" ng-controller="main" class="cloak">
<ng-include src="'/viatra/angular/blocks/header.html'"></ng-include>
<div class="clear"></div>
<div id="body_wrapper">
<h1 class="page_title">The Query API</h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This document provides an overview of the Java API of VIATRA Query, describing the features that will help you to integrate it into any Java application. This page is a detailed technical documentation, for basic usage information consult the <a href="tutorial.html#_using_queries_programmatically">the getting started tutorial</a> instead.</p>
</div>
<div class="paragraph">
<p>The most typical way of using the VIATRA Query API is to make use of the generated code that is found in the "src-gen" folder of your VIATRA Query project. This generated code provides easy and type-safe access to most of VIATRA Query&#8217;s features from Java code.</p>
</div>
<div class="paragraph">
<p>VIATRA Query also supports a "dynamic", generic API that allows to make use of patterns without relying on the generated code. The generic API shares functionality with the base classes of the "generated" API, and for most scenarios there is no performance difference between the two. A notable exception for this rule of thumb are <code>check() expressions</code>, where the generated code that is invoked through the generated API will execute the Java code instead of interpreting Xbase.</p>
</div>
<div id="toc" class="toc">
<div id="toctitle" class="title">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_most_important_classes_and_their_relationships">1. Most important classes and their relationships</a>
<ul class="sectlevel2">
<li><a href="#_match">1.1. Match</a></li>
<li><a href="#sec-querymatcher">1.2. Matcher</a></li>
<li><a href="#_helper_classes">1.3. Helper classes</a></li>
</ul>
</li>
<li><a href="#_lifecycle_management">2. Lifecycle management</a></li>
<li><a href="#_typical_programming_patterns">3. Typical programming patterns</a>
<ul class="sectlevel2">
<li><a href="#_loading_an_instance_model_and_executing_a_query">3.1. Loading an instance model and executing a query</a></li>
<li><a href="#_using_the_matchprocessor">3.2. Using the MatchProcessor</a></li>
<li><a href="#_matching_with_partially_bound_input_parameters">3.3. Matching with partially bound input parameters</a></li>
<li><a href="#_initialization_of_pattern_groups">3.4. Initialization of pattern groups</a></li>
</ul>
</li>
<li><a href="#_the_viatra_query_generic_api">4. The VIATRA Query Generic API</a></li>
<li><a href="#_viatra_query_base">5. VIATRA Query Base</a>
<ul class="sectlevel2">
<li><a href="#_extracting_reachability_paths_from_transitive_closure">5.1. Extracting reachability paths from transitive closure</a></li>
</ul>
</li>
<li><a href="#sec-query-scopes">6. Query Scopes</a>
<ul class="sectlevel2">
<li><a href="#_using_filtered_input_models_during_pattern_matching">6.1. Using Filtered Input Models During Pattern Matching</a></li>
</ul>
</li>
<li><a href="#_pattern_matching_with_local_search">7. Pattern matching with Local Search</a>
<ul class="sectlevel2">
<li><a href="#sec-localsearch">7.1. Using Local Search</a></li>
<li><a href="#_parameterizing_local_search">7.2. Parameterizing local search</a></li>
<li><a href="#_cost_function">7.3. Cost function</a></li>
<li><a href="#_known_limitations">7.4. Known limitations</a></li>
</ul>
</li>
<li><a href="#sec-query-hints">8. Providing Query Evaluation Hints</a></li>
<li><a href="#_query_specification_registry">9. Query specification registry</a>
<ul class="sectlevel2">
<li><a href="#_basic_usage">9.1. Basic usage</a></li>
<li><a href="#_advanced_usage">9.2. Advanced usage</a></li>
</ul>
</li>
<li><a href="#_performance_tuning_and_special_engine_modes">10. Performance tuning and special engine modes</a>
<ul class="sectlevel2">
<li><a href="#_query_groups_and_coalescing_model_traversals">10.1. Query groups and coalescing model traversals</a></li>
<li><a href="#_delaying_query_result_updates">10.2. Delaying query result updates</a></li>
<li><a href="#_run_once_query_engine">10.3. Run-once Query Engine</a></li>
</ul>
</li>
<li><a href="#_logging_in_viatra_query">11. Logging in VIATRA Query</a>
<ul class="sectlevel2">
<li><a href="#_configuration_problems">11.1. Configuration problems</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_most_important_classes_and_their_relationships"><a class="link" href="#_most_important_classes_and_their_relationships">1. Most important classes and their relationships</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>For every pattern definition, the VIATRA Query tooling generates a few classes:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">QuerySpecification</dt>
<dd>
<p>represents a pattern from a VQL file for the API specification. Not required to use for basic querying, only for generic APIs and fine-tuning settings.</p>
</dd>
<dt class="hdlist1">Match</dt>
<dd>
<p>binds the parameters of a query specification to elements from a model; represents a single result of a query or filters the results</p>
</dd>
<dt class="hdlist1">Matcher</dt>
<dd>
<p>provides functionality to retrieve the results of the query</p>
</dd>
<dt class="hdlist1">MatchProcessor</dt>
<dd>
<p>used to handle query results in a functional style (similar to Java Stream handling).</p>
</dd>
</dl>
</div>
<div class="sect2">
<h3 id="_match"><a class="link" href="#_match">1.1. Match</a></h3>
<div class="paragraph">
<p>A <strong>Match object</strong> represents a single match of the pattern, i.e. a tuple of objects whose members point to corresponding elements of the instance model (or scalar values) that the pattern is matched against. It is essentially a Data Transfer Object that is used to extract query result information from VIATRA Query, with an SQL analogy you could think of it as one "row" of the result set of a query. The generated fields correspond to the pattern header parameters.</p>
</div>
<div class="paragraph">
<p>You can also use <strong>Match</strong> objects to specify fixed input parameters to a query (while other fields can be left unspecified) - analogously to a "prepared" SQL statement that accepts input parameter bindings. In this case, the input Match will act as a filter (mask) and the results of you queries will also be instances of this class (where parameters already have the values given in the input). See TODO below for further details.</p>
</div>
<div class="paragraph">
<p>The code example below shows the <code>ApplicationInstancesMatch</code> class generated for the <strong>applicationInstances</strong> pattern (with a single parameter AI). The generated class implements the interface <code>IPatternMatch</code> through the <code>BasePatternMatch</code> internal implementation class.</p>
</div>
<div id="query-api-match" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public abstract class ApplicationInstancesMatch extends BasePatternMatch {
/** getters and setters for each parameter */
public ApplicationInstance getAI();
public void setAI(final ApplicationInstance pAI);
public String prettyPrint();
public int hashCode();
public boolean equals(final Object obj);
/** "reflective" calls **/
public ApplicationInstancesQuerySpecification specification();
public String patternName();
public List&lt;String&gt; parameterNames();
public Object get(final String parameterName);
public boolean set(final String parameterName, final Object newValue);
public Object[] toArray();
public ApplicationInstancesMatch toImmutable();
/* Mutable and immutable match instantiation */
public static ApplicationInstancesMatch newEmptyMatch();
public static ApplicationInstancesMatch newMutableMatch(final ApplicationInstance pAI);
public static ApplicationInstancesMatch newMatch(final ApplicationInstance pAI);
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="sec-querymatcher"><a class="link" href="#sec-querymatcher">1.2. Matcher</a></h3>
<div class="paragraph">
<p>The <strong>Matcher</strong> is the main entry point of the VIATRA Query API, with pattern-specific query methods. It provides access to the three key features of VIATRA Query:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>First of all it provides means to <strong>initialize a pattern matcher</strong> for a given Query engine.</p>
</li>
<li>
<p>After the initialization of the engine, the Matcher provides <strong>getter methods to retrieve the contents of the match set</strong>. For easy iteration over the match set it provides a convenience method (<code>forEachMatch</code>) as well, as this is the most frequent use case in our observation. Of course it contains other handy features (e.g.: <code>countMatches</code>, <code>hasMatch</code>) to help integration.</p>
</li>
<li>
<p>Finally, it provides means to efficiently <strong>track the changes in the match set</strong> in an event-driven fashion.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The example generated source code below demonstrates the <strong>ApplicationInstancesMatcher</strong> class generated for the <strong>eClassNames</strong> pattern from the running example. The matcher class implements the ViatraQueryMatcher generic interface, and its implementation code extends the <code>BaseGeneratedMatcher</code> internal class, inheriting several useful methods. In the listing below, we show some methods that are not actually part of generated code, but conform to the interface <code>ViatraQueryMatcher</code> and are accessible through inheritance from <code>BaseGeneratedMatcher</code>.</p>
</div>
<div id="query-api-matcher" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class EClassNamesMatcher implements ViatraQueryMatcher&lt;EClassNamesMatch&gt; {
/** factory method **/
public static ApplicationInstancesMatcher on(final ViatraQueryEngine engine) throws ViatraQueryException;
/** access to match set **/
public Collection&lt;ApplicationInstancesMatch&gt; getAllMatches(); // inherited
public Collection&lt;ApplicationInstancesMatch&gt; getAllMatches(final ApplicationInstance pAI);
public ApplicationInstancesMatch getOneArbitraryMatch(); // inherited
public ApplicationInstancesMatch getOneArbitraryMatch(final ApplicationInstance pAI);
public boolean hasMatch(); // inherited
public boolean hasMatch(final ApplicationInstance pAI);
public int countMatches(); // inherited
public int countMatches(final ApplicationInstance pAI);
/** Retrieve the set of values that occur in matches.**/
public Set&lt;ApplicationInstance&gt; getAllValuesOfAI() {}
/** iterate over matches using a lambda **/
public void forEachMatch(IMatchProcessor&lt;? super EClassNamesMatch&gt; processor); // inherited
public void forEachMatch(final ApplicationInstance pAI, final IMatchProcessor&lt;? super ApplicationInstancesMatch&gt; processor);
public void forOneArbitraryMatch(IMatchProcessor&lt;? super EClassNamesMatch&gt; processor); // inherited
public boolean forOneArbitraryMatch(final ApplicationInstance pAI, final IMatchProcessor&lt;? super ApplicationInstancesMatch&gt; processor) {}
/** Returns a new (partial) Match object for the matcher.
* This can be used e.g. to call the matcher with a partial match. **/
public ApplicationInstancesMatch newMatch(final ApplicationInstance pAI);
/** Access query specification */
public static IQuerySpecification&lt;ApplicationInstancesMatcher&gt; querySpecification() throws ViatraQueryException;
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_helper_classes"><a class="link" href="#_helper_classes">1.3. Helper classes</a></h3>
<div class="paragraph">
<p><code>MatchProcessor</code></p>
</div>
<div class="paragraph">
<p>The Matcher provides a function to iterate over the match set and invoke the process() method of the IMatchProcessor interface with every match. You can think of this as a "lambda" to ease typical query result processing tasks. To this end, an abstract processor class is generated, which you can override to implement the logic you would like to use. The abstract class unpacks the match variables so it can be used directly in the process() method.</p>
</div>
<div class="paragraph">
<p><code>QuerySpecification</code>: A pattern-specific specification that can instantiate a Matcher class in a type-safe way. You can get an instance of it via the Matcher class’s specification() method. The recommended way to instantiate a Matcher is with an <code>ViatraQueryEngine</code>. In both cases if the pattern is already registered (with the same root in the case of the Notifier method) then only a lightweight reference is created which points to the existing engine.</p>
</div>
<div class="paragraph">
<p>The code sample extends the BaseGeneratedQuerySpecification class.</p>
</div>
<div id="query-api-queryspecification" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">/**
* A pattern-specific query specification that can instantiate EClassNamesMatcher in a type-safe way.
*/
public final class ApplicationInstancesQuerySpecification extends BaseGeneratedEMFQuerySpecification&lt;ApplicationInstancesMatcher&gt; {
/** Singleton instance access */
public static ApplicationInstancesQuerySpecification instance() throws ViatraQueryException;
/** Instantiate matches and matchers */
public ApplicationInstancesMatcher instantiate() throws ViatraQueryException;
public ApplicationInstancesMatch newEmptyMatch();
public ApplicationInstancesMatch newMatch(final Object... parameters);
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_lifecycle_management"><a class="link" href="#_lifecycle_management">2. Lifecycle management</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>In VIATRA Query, all pattern matching (query evaluation) is carried out in <strong>ViatraQueryEngine</strong> instances that are accessed through the user-friendly generated classes of the public API. The <strong>ViatraQueryEngine</strong> associated to your patterns can be accessed and managed through the <strong>EngineManager</strong> singleton class, to track and manipulate their lifecycles.</p>
</div>
<div class="paragraph">
<p>A ViatraQueryEngine is instantiated with a Scope implementation that describes the model the query should work with. By default, in case of EMF it is recommended to initialize an EMFScope instance with the ResourceSet containing the EMF model. For more details about scopes see <a href="#sec-query-scopes">Query Scopes</a>.</p>
</div>
<div class="paragraph">
<p>By default, for each scope a single, managed <strong>ViatraQueryEngine</strong> is created, which is shared by all objects that access VIATRA Query&#8217;s features through the generated API. The <strong>ViatraQueryEngine</strong> is attached to the scope and <strong>it is retained on the heap as long as the model itself is there</strong>. It will listen on update notifications stemming from the given model in order to maintain live results. If you release all references to the model (e.g. unload the resource), the <strong>ViatraQueryEngine</strong> can also be garbage collected (as long as there are no other inbound references on it).</p>
</div>
<div class="paragraph">
<p>In all, for most (basic) scenarios, the following workflow should be followed:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>initialize/load the model</p>
</li>
<li>
<p>initialize your <strong>ViatraQueryEngine</strong> instance</p>
</li>
<li>
<p>initialize pattern matchers, or groups of pattern matchers and use them</p>
</li>
<li>
<p>if you release the model and your <strong>ViatraQueryEngine</strong> instance, all resources will be freed by the garbage collector.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For advanced scenarios (if you wish to manage lifecycles at a more finegrained level), you have the option of creating <strong>unmanaged</strong> ViatraQueryEngines and dispose of them independently of your instance model. For most use-cases though, we recommend the use of managed engines, this is the default and optimized behavior, as these engines can share common indices and caches to save memory and CPU time. The <strong>EngineManager</strong> ensures that there will be no duplicated engine for the same model root (Notifier) object. Creating an unmanaged engine will give you certain additional benefits, however additional considerations should be applied.</p>
</div>
<div class="paragraph">
<p>If you want to remove the matchers from the engine you can call the <code>wipe()</code> method on it. It discards any pattern matcher caches and forgets the known patterns. The base index built directly on the underlying EMF model, however, is kept in memory to allow reuse when new pattern matchers are built. If you don’t want to use it anymore call the <code>dispose()</code> instead, to completely disconnect and dismantle the engine.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
Never call wipe or dispose on any engine that were not explicitly created by you; any created matcher over the engine becomes unusable.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_typical_programming_patterns"><a class="link" href="#_typical_programming_patterns">3. Typical programming patterns</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>In the followings, we provide short source code samples (with some explanations) that cover the most important use-cases supported by the VIATRA Query API.</p>
</div>
<div class="sect2">
<h3 id="_loading_an_instance_model_and_executing_a_query"><a class="link" href="#_loading_an_instance_model_and_executing_a_query">3.1. Loading an instance model and executing a query</a></h3>
<div id="query-api-loadmodelandquery" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">// get all matches of the pattern
// initialization
// phase 1: (managed) ViatraQueryEngine
ViatraQueryEngine engine = ViatraQueryEngine.on(new EMFScope(resource /* or resourceSet */));
// phase 2: the matcher itself
EObjectMatcher matcher = EObjectMatcher.on(engine);
// get all matches of the pattern
Collection&lt;EObjectMatch&gt; matches = matcher.getAllMatches();
// process matches, produce some output
StringBuilder results = new StringBuilder();
prettyPrintMatches(results, matches);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_using_the_matchprocessor"><a class="link" href="#_using_the_matchprocessor">3.2. Using the MatchProcessor</a></h3>
<div class="paragraph">
<p>With the MatchProcessor you can iterate over the matches of a pattern quite easily:</p>
</div>
<div id="query-api-matchprocessor" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">matcher2.forEachMatch(new EClassNamesProcessor() {
@Override
public void process(EClass c, String n) {
results.append("\tEClass: " + c.toString() + "\n");
}
});</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_matching_with_partially_bound_input_parameters"><a class="link" href="#_matching_with_partially_bound_input_parameters">3.3. Matching with partially bound input parameters</a></h3>
<div class="paragraph">
<p>An important aspect of VIATRA Query queries is that they are <strong>bidirectional</strong> in the sense that they accept input bindings, to filter/project the result set with a given input constraint. The following example illustrates the usage of the match processor with an input binding that restricts the result set to the cases where the second parameter (the name of the EClass) takes the value "A":</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">matcher2.forEachMatch( matcher2.newMatch(null, "A") , new EClassNamesProcessor() {
@Override
public void process(EClass c, String n) {
results.append("\tEClass with name A: " + c.toString() + "\n");
}
});
// alternatively:
matcher2.forEachMatch(null, "A" , new EClassNamesProcessor() {
@Override
public void process(EClass c, String n) {
results.append("\tEClass with name A: " + c.toString() + "\n");
}
});</code></pre>
</div>
</div>
<div class="paragraph">
<p>The input bindings may be used for all match result set methods.</p>
</div>
<div class="paragraph">
<p>Additionally, the <strong>getAllValuesOf&#8230;&#8203;</strong> methods allow you to perform projections of the result set to one of the parameters:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">// projections
for (EClass ec: matcher2.getAllValuesOfc(matcher2.newMatch(null,"A")))
{
results.append("\tEClass with name A: " + ec.toString() + "\n");
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_initialization_of_pattern_groups"><a class="link" href="#_initialization_of_pattern_groups">3.4. Initialization of pattern groups</a></h3>
<div class="paragraph">
<p>Using pattern groups is important for performance. By default, VIATRA Query performs a traversal of the instance model when a matcher is accessed through the <strong>ViatraQueryEngine</strong> for the first time. If you wish to use several pattern matchers, it is a good idea to make use of the generated pattern group class and prepare the ViatraQueryEngine to perform a combined traversal (with minimal additional overhead) so that any additional Matcher initializations avoid re-traversals.</p>
</div>
<div id="query-api-groupinit" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">// phase 1: (managed) ViatraQueryEngine
ViatraQueryEngine engine = ViatraQueryEngine.on(new EMFScope(resource));
// phase 2: the group of pattern matchers
HeadlessQueries patternGroup = HeadlessQueries.instance();
patternGroup.prepare(engine);
// from here on everything is the same
EObjectMatcher matcher = EObjectMatcher.on(engine);
// get all matches of the pattern
Collection&lt;EObjectMatch&gt; matches = matcher.getAllMatches();
prettyPrintMatches(results, matches);
// ... //
// matching with partially bound input parameters
// because EClassNamesMatcher is included in the patterngroup, *no new traversal* will be done here
EClassNamesMatcher matcher2 = EClassNamesMatcher.on(engine);</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_viatra_query_generic_api"><a class="link" href="#_the_viatra_query_generic_api">4. The VIATRA Query Generic API</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>All features provided by the generated pattern matcher API can be executed using the generic pattern matcher API of VIATRA. This generic API differs from the generated one in two key aspects:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>it can be used to apply queries and use other VIATRA Query features <strong>without</strong> generating code and loading the resulting bundles into the running configuration. In other words, you just need to supply the EMF-based in-memory representation (an instance of the Pattern class)</p>
</li>
<li>
<p>the generic API is not "type safe" in the sense that the Java types of your pattern variables is not known and needs to be handled dynamically (typically by type casting).</p>
</li>
</ul>
</div>
<div id="query-api-genericapi" class="listingblock">
<div class="title">Example using the generic API</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public String executeDemo_GenericAPI_LoadFromEIQ(String modelPath, String patternFQN) {
final StringBuilder results = new StringBuilder();
Resource resource = loadModel(modelPath);
if (resource != null) {
try {
// get all matches of the pattern
// create an *unmanaged* engine to ensure that noone else is going
// to use our engine
AdvancedViatraQueryEngine engine = AdvancedViatraQueryEngine.createUnmanagedEngine(resource);
// instantiate a pattern matcher through the registry, by only knowing its FQN
// assuming that there is a pattern definition registered matching 'patternFQN'
Pattern p = null;
// Initializing Xtext-based resource parser
// Do not use if VIATRA Query tooling is loaded!
EMFPatternLanguageStandaloneSetup.createInjectorAndDoEMFRegistration();
//Loading pattern resource from file
ResourceSet resourceSet = new ResourceSetImpl();
URI fileURI = URI.createPlatformPluginURI("headlessQueries.incquery/src/headless/headlessQueries.vql", false);
Resource patternResource = resourceSet.getResource(fileURI, true);
// navigate to the pattern definition that we want
if (patternResource != null) {
if (patternResource.getErrors().size() == 0 &amp;&amp; patternResource.getContents().size() &gt;= 1) {
EObject topElement = patternResource.getContents().get(0);
if (topElement instanceof PatternModel) {
for (Pattern _p : ((PatternModel) topElement).getPatterns()) {
if (patternFQN.equals(CorePatternLanguageHelper.getFullyQualifiedName(_p))) {
p = _p; break;
}
}
}
}
}
if (p == null) {
throw new RuntimeException(String.format("Pattern %s not found", patternFQN));
}
// A specification builder is used to translate patterns to query specifications
SpecificationBuilder builder = new SpecificationBuilder();
// attempt to retrieve a registered query specification
ViatraQueryMatcher&lt;? extends IPatternMatch&gt; matcher = engine.getMatcher(builder.getOrCreateSpecification(p));
if (matcher!=null) {
Collection&lt;? extends IPatternMatch&gt; matches = matcher.getAllMatches();
prettyPrintMatches(results, matches);
}
// wipe the engine
engine.wipe();
// after a wipe, new patterns can be rebuilt with much less overhead than
// complete traversal (as the base indexes will be kept)
// completely dispose of the engine once's it is not needed
engine.dispose();
resource.unload();
} catch (ViatraQueryException e) {
e.printStackTrace();
results.append(e.getMessage());
}
} else {
results.append("Resource not found");
}
return results.toString();
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_viatra_query_base"><a class="link" href="#_viatra_query_base">5. VIATRA Query Base</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>VIATRA Query provides a light-weight indexer library called Base that aims to provide several useful (some would even argue critical) features for querying EMF models:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>inverse navigation along EReferences</p>
</li>
<li>
<p>finding and incrementally tracking all model elements by attribute value/type (i.e. inverse navigation along EAttributes)</p>
</li>
<li>
<p>incrementally computing transitive reachability along given reference types (i.e. transitive closure of an EMF model)</p>
</li>
<li>
<p>getting and tracking all the (direct) instances of a given EClass</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The point of VIATRA Query Base is to provide all of these in an incremental way, which means that once the query evaluator is attached to an EMF model, as long as it stays attached, the query results can be retrieved instantly (as the query result cache is automatically updated). VIATRA Query Base is a lightweight, small Java library that can be integrated easily to any EMF-based tool as it can be used in a stand-alone way, without the rest of VIATRA Query.</p>
</div>
<div class="paragraph">
<p>We are aware that some of the functionality can be found in some Ecore utility classes (for example ECrossReferenceAdapter). These standard implementations are non-incremental, and are thus do not scale well in scenarios where high query evaluation performance is necessary (such as e.g. on-the-fly well-formedness validation or live view maintenance). VIATRA Query Base has an additional important feature that is not present elsewhere: it contains very efficient implementations of transitive closure that can be used e.g. to maintain reachability regions incrementally, in very large EMF instance models.</p>
</div>
<div class="sect2">
<h3 id="_extracting_reachability_paths_from_transitive_closure"><a class="link" href="#_extracting_reachability_paths_from_transitive_closure">5.1. Extracting reachability paths from transitive closure</a></h3>
<div class="paragraph">
<p>Beyond the support for querying reachability information between nodes in the model, the TransitiveClosureHelper class also provides the functionality to retrieve paths between pairs of nodes. The <code>getPathFinder</code> method returns an <code>IGraphPathFinder</code> object, which exposes the following operations:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>Deque&lt;V&gt; getPath(V sourceNode, V targetNode)</code></dt>
<dd>
<p>Returns an arbitrary path from the source node to the target node (if such exists).</p>
</dd>
<dt class="hdlist1"><code>Iterable&lt;Deque&lt;V&gt;&gt; getShortestPaths(V sourceNode, V targetNode)</code></dt>
<dd>
<p>Returns the collection of shortest paths from the source node to the target node (if such exists).</p>
</dd>
<dt class="hdlist1"><code>Iterable&lt;Deque&lt;V&gt;&gt; getAllPaths(V sourceNode, V targetNode)</code></dt>
<dd>
<p>Returns the collection of paths from the source node to the target node (if such exists).</p>
</dd>
<dt class="hdlist1"><code>Iterable&lt;Deque&lt;V&gt;&gt; getAllPathsToTargets(V sourceNode, Set&lt;V&gt; targetNodes)</code></dt>
<dd>
<p>Returns the collection of paths from the source node to any of the target nodes (if such exists).</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Internally these operations use a depth-first-search traversal and rely on the information which is incrementally maintained by the transitive closure component.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="sec-query-scopes"><a class="link" href="#sec-query-scopes">6. Query Scopes</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>VIATRA Query uses the concept of <strong>Scopes</strong> to define the entire model to search for results. For queries over EMF models, the EMFScope class defines such scopes. When initializing a ViatraQueryEngine, it is required to specify this scope by creating a new instance of EMFScope.</p>
</div>
<div class="paragraph">
<p>This instance might be created from one or more Notifier instances (ResourceSet: includes all model elements stored in the ResourceSet; Resource: includes all elements inside the corresponding Resource; EObject: includes all elements in the containment subtree of the object itself).</p>
</div>
<div class="paragraph">
<p>In most cases, it is recommended to include the entire ResourceSet as the query scope; however, if required, it is possible to</p>
</div>
<div class="sect2">
<h3 id="_using_filtered_input_models_during_pattern_matching"><a class="link" href="#_using_filtered_input_models_during_pattern_matching">6.1. Using Filtered Input Models During Pattern Matching</a></h3>
<div class="paragraph">
<p>In several cases it is beneficial to not include all Resources from a ResourceSet during pattern matching, but consider more than one. Such cases might include Xtext/Xbase languages or <a href="http://www.jamopp.org/index.php/JaMoPP">JaMoPP</a>-based instances that include resources representing the classes of the Java library.</p>
</div>
<div class="paragraph">
<p>In case of EMF models, the EMFScope instance may also set some base index options to filter out containment subtrees from being indexed both by the Base Indexer and the Rete networks, by providing a filter implementation to the VIATRA Query Engine. These options include the IBaseIndexResourceFilter and IBaseIndexObjectFilter instances that can be used to filter out entire resources or containment subtrees, respectively.</p>
</div>
<div class="paragraph">
<p>Sample usage (by filtering out Java classes referred by JaMoPP):</p>
</div>
<div id="query-runtime-filteredscope" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">ResourceSet resourceSet = ...; //Use a Resource Set as the root of the engine
BaseIndexOptions options = new BaseIndexOptions().withResourceFilterConfiguration(new IBaseIndexResourceFilter() {
@Override
public boolean isResourceFiltered(Resource resource) {
// PathMap URI scheme is used to refer to JDK classes
return "pathmap".equals(resource.getURI().scheme());
}
});
//Initializing scope with custom options
EMFScope scope = new EMFScope(resourceSet, options);
ViatraQueryEngine engine = ViatraQueryEngine.on(scope);</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
there are some issues to be considered while using this API:
</td>
</tr>
</table>
</div>
<div class="ulist">
<ul>
<li>
<p>If a Resource or containment subtree is filtered out, it is filtered out entirely. It is not possible to re-add some lower-level contents.</p>
</li>
<li>
<p>In case of the query scope is set to a subset of the entire model (e.g only one EMF resource within the resource set), model elements within the scope of the engine may have references pointing to elements outside the scope; these are called <strong>dangling edges</strong>. Previous versions of VIATRA made the assumption that the model is self-contained and free of dangling edges; the behavior of the query engine was ''unspecified'' (potentially incorrect match sets) if the model did not have this property. In VIATRA 1.6, this behavior was cleaned up by adding a new indexer mode that drops this assumption, and (with a minor cost to performance) always checks both ends of all indexed edges to be in-scope. For backward compatibility, the old behavior is used by default, but you can manually change this using the corresponding base index option as below. For new code we suggest to use this option to drop the dangling-free assumption, as it provides more consistent and intuitive results in a lot of cases; in a future VIATRA release this will be the new default.</p>
</li>
</ul>
</div>
<div id="query-runtime-danglingfree" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">BaseIndexOptions options = new BaseIndexOptions().withDanglingFreeAssumption(false);
ResourceSet rSet = new ResourceSetImpl();
EMFScope scope = new EMFScope(rSet, options);
ViatraQueryEngine engine = ViatraQueryEngine.on(scope);</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_pattern_matching_with_local_search"><a class="link" href="#_pattern_matching_with_local_search">7. Pattern matching with Local Search</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Since version 0.9, there is a possibility to refer to alternative search engines in addition to Rete-based incremental engines; version 1.0 includes a local search based search algorithm usable with the VIATRA Query matcher API.</p>
</div>
<div class="paragraph">
<p>Since version 1.4, the Local Search engine is considered stable, and users are encuraged to use it in applications where incrementality is not crucial. The Local Search engine reuses the same matcher API used in VIATRA Query.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>When is local search the most beneficial?</p>
<div class="ulist">
<ul>
<li>
<p>A single, batch evaluation of models</p>
</li>
<li>
<p>Memory limit is severe and the Rete network does not fit into the memory</p>
</li>
<li>
<p>When all calls have one or more parameters bound, resulting in simple traversal</p>
</li>
</ul>
</div>
</li>
<li>
<p>Harder cases</p>
<div class="ulist">
<ul>
<li>
<p>Repeated model execution</p>
</li>
<li>
<p>Query evaluation requires expensive model traversal (think about iterating over all instances in a model)</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="sec-localsearch"><a class="link" href="#sec-localsearch">7.1. Using Local Search</a></h3>
<div class="paragraph">
<p>The most important steps to perform:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Add a dependency to the optional plug-in <code>org.eclipse.viatra.query.runtime.localsearch</code></p>
</li>
<li>
<p>Explicitly ask for a local search-based matcher when initializing the matcher instance:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre>IQuerySpecification&lt;?&gt; specification = ...;
QueryEvaluationHint hint = LocalSearchHints.getDefault().build();
AdvancedViatraQueryEngine.from(queryEngine).getMatcher(specification, hint);</pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Or alternatively, set the local search as default for a query engine:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre>// Access the default local search hint
QueryEvaluationHint localSearchHint = LocalSearchHints.getDefault().build();
// Build an engine options with the local search hint
ViatraQueryEngineOptions options = ViatraQueryEngineOptions.
defineOptions().
withDefaultHint(localSearchHint).
withDefaultBackend(localSearchHint.getQueryBackendFactory()). // this line is needed in 1.4 due to bug 507777
build();
//Access the query engine
ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope, options);</pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>After initialization, the existing <a href="#sec-querymatcher">pattern matcher API</a> constructs can be used over the local search engine.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>It is also possible to declare specific patterns to be executed by Local Search in the VQL file using the <code>search</code>, although this setting may be overridden by the hints given at the matcher creation.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">search pattern minCPUs(n : java Integer) {
n == min find cpus(_hi1, #_);
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_parameterizing_local_search"><a class="link" href="#_parameterizing_local_search">7.2. Parameterizing local search</a></h3>
<div class="paragraph">
<p>Parameterization of the planner algorithm is possible via <a href="#sec-query-hints">the hint mechanism</a>. Currently (version 1.7) the following hints are available by using the <code>LocalSearchHints</code> builder class:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Use Base</dt>
<dd>
<p>allow/disallow the usage of the index at runtime. Its value may be <code>true</code> or <code>false</code>. The default value is <code>true</code>.</p>
</dd>
<dt class="hdlist1">Row Count</dt>
<dd>
<p>An internal parameter, bigger values often mean longer plan generation times, and potentially search plans with lower cost. Its value may be a positive <code>int</code>, the default value is 4.</p>
</dd>
<dt class="hdlist1">Cost Function</dt>
<dd>
<p>The cost function to be used by the planner. Must implement org.eclipse.viatra.query.runtime.localsearch.planner.cost.ICostFunction</p>
</dd>
<dt class="hdlist1">Flatten call predicate</dt>
<dd>
<p>The predicate to control which pattern composition calls shall be flattened before planning. By deafult all called patterns are flattened.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>For example, to disable the use of base index:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">IQuerySpecification&lt;?&gt; specification = ...;
QueryEvaluationHint hint = LocalSearchHints.getDefault().setUseBase(false).build();
AdvancedViatraQueryEngine.from(queryEngine).getMatcher(specification, hint);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_cost_function"><a class="link" href="#_cost_function">7.3. Cost function</a></h3>
<div class="paragraph">
<p>The default cost function estimates operation costs based on the statistical structure of the model, which is obtained using the base index. This is true even if USE_BASE_INDEX is set to false, in which case a plan is created which does not rely on the base index at execution time. Since 1.4.0 the base index is capable of providing only statistical information with much less overhead compared to instance indexing. To avoid using base index even in the planning phase, the cost function can be replaced to another implementation. For this purpose, two alternative implementations are provided:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>VariableBindingBasedCostFunction</code> estimates the operation costs using the number of variables it binds. This cost function usually results in lower performance executions.</p>
</li>
<li>
<p>The abstract class <code>StatisticsBasedConstraintCostFunction</code> can be used to provide model statistics from different sources, e.g. a previously populated map:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">final Map&lt;IInputKey, Long&gt; statistics = ..
QueryEvaluationHint hint = LocalSearchHints.getDefault().setCostFunction(new StatisticsBasedConstraintCostFunction(){
public long countTuples(IConstraintEvaluationContext input, IInputKey supplierKey){
return statistics.get(supplierKey);
}
}).build();</code></pre>
</div>
</div>
<div class="paragraph">
<p>The latter is advised to be used if the model is expected to be changed after the planning phase to ensure that the planing is based on a realistic model statistics which resembles the actual structure which the pattern is executed on.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
We plan on providing a simpler way of setting up model statistics in later versions; this kind of setup might be changed.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_known_limitations"><a class="link" href="#_known_limitations">7.4. Known limitations</a></h3>
<div class="ulist">
<ul>
<li>
<p>A local search matcher cannot provide change notifications on pattern matches. If asked, an UnsupportedOperationException is thrown.</p>
</li>
<li>
<p>As of version 1.4, it is not possible to combine different pattern matching algorithms for the evaluation of a single pattern. Either the entire search must use Rete or Local search based algorithms.</p>
</li>
<li>
<p>The Local Search engine currently does not able to execute recursive queries. See <a href="http://bugs.eclipse.org/458278" class="bare">http://bugs.eclipse.org/458278</a> for more details.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="sec-query-hints"><a class="link" href="#sec-query-hints">8. Providing Query Evaluation Hints</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>It is possible to pass extra information to the runtime of VIATRA Query using evaluation hints, such as information about the structure of the model or requirements for the evaluation. In version 1.4, the handling of such hints were greatly enhanced, allowing the following ways to pass hints:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>The Query engine might be initialized with default hints using the static method <code>AdvancedQueryEngine#createUnmanagedEngine(QueryScope, ViatraQueryEngineOptions)</code>. The hints provided inside the query engine options are the default hints used by all matchers, but can be overridden using the following options.</p>
</li>
<li>
<p>A pattern definition can be extended with hints, e.g. for backend selection in the pattern language. Such hints will be generated into the generated query specification code.</p>
</li>
<li>
<p>When accessing a new pattern matcher through the Query Engine, further override hints might be presented using <code>AdvancedQueryEngine#getMatcher(IQuerySpecification, QueryEvaluationHint)</code>. Such hints override both the engine default and the pattern default hints.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>In version 1.4 the hints are mostly used to fine tune the <a href="#sec-localsearch">local search based pattern matcher</a>, but their usage is gradually being extended. See classes <code>ReteHintOptions</code> and <code>LocalSearchHints</code> for hint options provided by the query backends.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_query_specification_registry"><a class="link" href="#_query_specification_registry">9. Query specification registry</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The query specification registry, available since ''VIATRA 1.3'' is used to manage query specifications provided by multiple connectors which can
dynamically add and remove specifications. Users can read the contents of the registry through views that are also
dynamically updated when the registry is changed by the connectors.</p>
</div>
<div class="sect2">
<h3 id="_basic_usage"><a class="link" href="#_basic_usage">9.1. Basic usage</a></h3>
<div class="paragraph">
<p>The most common usage of the registry will be to get a registered query specification based on its fully qualified name.
You can access the registry through a singleton instance:</p>
</div>
<div id="query-runtime-registry-usage" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">IQuerySpecificationRegistry registry = org.eclipse.viatra.query.runtime.registry.QuerySpecificationRegistry.getInstance();
IQuerySpecification&lt;?&gt; specification = registry.getDefaultView().getEntry("my.registered.query.fqn").get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>The default view lets you access the contents of the registry, the entry returned is a provider for the query specification that returns it when requested through the get() method.</p>
</div>
</div>
<div class="sect2">
<h3 id="_advanced_usage"><a class="link" href="#_advanced_usage">9.2. Advanced usage</a></h3>
<div class="sect3">
<h4 id="_views"><a class="link" href="#_views">9.2.1. Views</a></h4>
<div class="paragraph">
<p>To get an always up to date view of the registry, you can either:
* request a <strong>default view</strong> that will contain on specification marked to be included in this view (e.g. queries registered through the queryspecification extension point)
* create a new <strong>view</strong> that may use either a filter or a factory for defining which specifications should be included in the view</p>
</div>
<div id="query-api-registry-views" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">IQuerySpecificationRegistry registry = QuerySpecificationRegistry.getInstance();
// access default view
IDefaultRegistryView defaultView = registry.getDefaultView();
// create new view
IRegistryView simpleView = registry.createView();
// create filtered view
IRegistryView filteredView = registry.createView(new IRegistryViewFilter() {
@Override
public boolean isEntryRelevant(IQuerySpecificationRegistryEntry entry) {
// return true to include in view
}
});
// create specific view instance
boolean allowDuplicateFQNs = false;
IRegistryView ownView = registry.createView(new IRegistryViewFactory() {
return new AbstractRegistryView(registry, allowDuplicateFQNs) {
@Override
protected boolean isEntryRelevant(IQuerySpecificationRegistryEntry entry) {
// return true to include in view
}
}
);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Once you have a view instance, you can access the contents of the registry by requesting the entries from the view or adding a listener that will be notified when the view changes.</p>
</div>
<div class="paragraph">
<p>Default views add a few additional utilities that are made possible by also restricting what is included in them. Default views will only contain entries that are marked explicitly to be included and will not allow different specifications with the same fully qualified name. In return, you can request a single entry by its FQN (since at most one can exist) and also request a query group that contains all entries.</p>
</div>
</div>
<div class="sect3">
<h4 id="_listening_to_view_changes"><a class="link" href="#_listening_to_view_changes">9.2.2. Listening to view changes</a></h4>
<div class="paragraph">
<p>The contents of the registry may change after a view is created. When you access the view to get its entries, it will always return the current state of the registry.
If you want to get notified when the contents of your view change, you can add a listener to the view:</p>
</div>
<div id="query-api-registry-listener" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">IQuerySpecificationRegistry registry = QuerySpecificationRegistry.getInstance();
IRegistryView myView = registry.createView();
IQuerySpecificationRegistryChangeListener listener = new IQuerySpecificationRegistryChangeListener() {
@Override
public void entryAdded(IQuerySpecificationRegistryEntry entry) {
// process addition
}
@Override
public void entryRemoved(IQuerySpecificationRegistryEntry entry) {
// process removal
}
});
myView.addViewListener(listener);
// when you don't need to get notifications any more
myView.removeViewListener(listener);</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Important note:</strong> your code has to keep a reference to your view otherwise it will be garbage collected. The registry uses weak references to created views in order to free users from having to manually dispose views.</p>
</div>
</div>
<div class="sect3">
<h4 id="_adding_specifications_to_the_registry"><a class="link" href="#_adding_specifications_to_the_registry">9.2.3. Adding specifications to the registry</a></h4>
<div class="paragraph">
<p>The registry is supplied with specifications through sources. You can add your own source connector as a source and dynamically add and remove your own specifications.</p>
</div>
<div id="query-api-registry-addspecification" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">IQuerySpecificationRegistry registry = QuerySpecificationRegistry.getInstance();
// initialize your connector
IRegistrySourceConnector connector;
// add connector
boolean sourceAdded = registry.addSource(connector);
// [...]
// remove your source when needed
boolean sourceRemoved = registry.removeSource(connector);</code></pre>
</div>
</div>
<div class="paragraph">
<p>We already have some connector implementations for the most common use cases. For example, you can create a connector with a simple add and remove method for query specifications:</p>
</div>
<div id="query-api-registry-connectors" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">IRegistrySourceConnector connector = new SpecificationMapSourceConnector("my.source.identifier", false /* do not include these in default views */);
IQuerySpecification&lt;?&gt; specification = /* available from somewhere */
IQuerySpecificationProvider provider = new SingletonQuerySpecificationProvider(specification);
// add specification to source
connector.addQuerySpecificationProvider(provider);
// remove specification by FQN
connector.removeQuerySpecificationProvider(specification.getFullyQualifiedName());</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_performance_tuning_and_special_engine_modes"><a class="link" href="#_performance_tuning_and_special_engine_modes">10. Performance tuning and special engine modes</a></h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_query_groups_and_coalescing_model_traversals"><a class="link" href="#_query_groups_and_coalescing_model_traversals">10.1. Query groups and coalescing model traversals</a></h3>
<div class="paragraph">
<p>If you initialize a new query that requires the indexing of some EMF types for which the current engine instance has not yet built an index, then the base index of the VIATRA engine will traverse the entire scope to build the index. It can make a great difference if such expensive re-traversals are avoided, and the engine traverses the model only once to build indexes for all queries.</p>
</div>
<div class="paragraph">
<p>The easiest wax to do this would be to use &lt;code&gt;IQueryGroup.prepare(engine)&lt;/code&gt; for a group of queries. Such a group is generated for every query file, and any other custom group can be manually assembled with &lt;code&gt;GenericQueryGroup&lt;/code&gt;.</p>
</div>
<div id="query-api-group-prepare" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">IQueryGroup queries = ...
ViatraQueryEngine engine = ...
queries.prepare(engine);</code></pre>
</div>
</div>
<div class="paragraph">
<p>For advanced use cases, it is possible to directly control indexing traversals in an arbitrary code block, such that any index constructions are coalesced into a single traversal:</p>
</div>
<div id="query-api-coalesce" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">ViatraQueryEngine engine = ...
engine.getBaseIndex().coalesceTraversals(new Callable&lt;Void&gt;() {
@Override
public Void call() throws Exception {
// obtain matchers, etc.
return null;
}
});</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_delaying_query_result_updates"><a class="link" href="#_delaying_query_result_updates">10.2. Delaying query result updates</a></h3>
<div class="paragraph">
<p>As of version 1.6, the advanced query API now includes a feature that lets users temporarily "turn off" query result maintenance in the incremental query backend. During such a code block, only the base model indexer is updated, query results remain stale until the end of the block. The advantage is that it is possible to save significant execution time when changing the model in a way that partially undoes itself, e.g. a large part of the model is removed and then re-added.</p>
</div>
<div id="query-api-delayupdates" class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">AdvancedViatraQueryEngine engine = ...
engine.delayUpdatePropagation(new Callable&lt;Void&gt;() {
@Override
public Void call() throws Exception {
// perform extensive changes in model that largely cancel each other out
return null;
}
});</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_run_once_query_engine"><a class="link" href="#_run_once_query_engine">10.3. Run-once Query Engine</a></h3>
<div class="paragraph">
<p>This page describes how VIATRA Query can be used to carry out one-time query evaluation which is useful in the following cases:
* You want less (steady-state) memory consumption instead of incremental evaluation.
* You have derived features that are not [[VIATRA/Addon/Query_Based_Features#Well-behaving_structural_features|well-behaving]], but you want to include them in queries.
* You like the query language of VIATRA Query, but you don&#8217;t need incremental evaluation and the batch performance is better than the sum of model modification overheads between query usages.</p>
</div>
<div class="paragraph">
<p>These scenarios are now supported by a "run-once" query engine that will perform the evaluation on a given query and return the match set then dispose of the Rete network and base index to free up memory.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The <a href="#sec-localsearch">local search engine</a> provided by VIATRA should perform better for these cases and it is recommended to use that instead. This functionality predates local search support and is kept for backward compatibility.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_example"><a class="link" href="#_example">10.3.1. Example</a></h4>
<div class="paragraph">
<p>The most up-to-date sample source code to this page is found in Git here: <a href="http://git.eclipse.org/c/viatra/org.eclipse.viatra.git/tree/examples/minilibrary" class="bare">http://git.eclipse.org/c/viatra/org.eclipse.viatra.git/tree/examples/minilibrary</a> Most notably,</p>
</div>
<div class="ulist">
<ul>
<li>
<p>the patterns are found in <a href="http://git.eclipse.org/c/viatra/org.eclipse.viatra.git/tree/examples/minilibrary/org.eclipse.viatra.query.runtime.runonce.tests/src/org/eclipse/viatra/query/runtime/runonce/tests/eiqlibrary.vql">eiqlibrary.vql</a></p>
</li>
<li>
<p>and the API usage samples are found in <a href="http://git.eclipse.org/c/viatra/org.eclipse.viatra.git/tree/examples/minilibrary/org.eclipse.viatra.query.runtime.runonce.tests/src/org/eclipse/viatra/query/runtime/runonce/tests/RunOnceTest.java">RunOnceTest.java</a></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_usage"><a class="link" href="#_usage">10.3.2. Usage</a></h4>
<div class="sect4">
<h5 id="_run_once_then_dispose"><a class="link" href="#_run_once_then_dispose">10.3.2.1. Run-once then dispose</a></h5>
<div class="paragraph">
<p>The API of the run-once query engine is very simple, just instantiate the engine with the constructor using the proper scope (EObject, Resource or ResourceSet) and call the getAllMatches with a query specfication:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">RunOnceQueryEngine engine = new RunOnceQueryEngine(notifier);
// using generated query specification
Collection&lt;SumOfPagesInLibraryMatch&gt; allMatches = engine.getAllMatches(SumOfPagesInLibraryMatcher.querySpecification());
// if you only have Pattern object
IQuerySpecification&lt;ViatraQueryMatcher&lt;IPatternMatch&gt;&gt; specification = (IQuerySpecification&lt;ViatraQueryMatcher&lt;IPatternMatch&gt;&gt;) QuerySpecificationRegistry.getOrCreateQuerySpecification(BooksWithMultipleAuthorsMatcher.querySpecification().getPattern());
Collection&lt;IPatternMatch&gt; matches = engine.getAllMatches(specification);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that each invocation of getAllMatches will traverse the model completely, index the classes, features and data types that are required for the query, collect the match set than dispose the indexes.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_automatic_re_sampling"><a class="link" href="#_automatic_re_sampling">10.3.3. Automatic re-sampling</a></h4>
<div class="paragraph">
<p>In many cases, the derived features are only a small part of the queries and it would be better to keep the indices once they are built. However, in this case, we need a way to update the values of all derived features that are indexed.</p>
</div>
<div class="paragraph">
<p>The run-once query engine supports automatic re-sampling by listening to model modifications and updating values before returning match results.The following example shows how you can enable this mode:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">RunOnceQueryEngine engine = new RunOnceQueryEngine(notifier);
engine.setAutomaticResampling(true); // enable re-sampling mode
Collection&lt;SumOfPagesInLibraryMatch&gt; allMatches = engine.getAllMatches(SumOfPagesInLibraryMatcher.querySpecification());
// some model modification
// only re-sampling of derived features, not complete traversal
allMatches = engine.getAllMatches(SumOfPagesInLibraryMatcher.querySpecification());</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you no longer need automatic re-sampling, you can turn it off. In this case the engine that was kept incrementally updated is removed from memory.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">engine.setAutomaticResampling(false); // disable re-sampling mode, indices removed</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, if the value of derived features change without any model modifications (not recommended), you can tell the engine to run the re-sampling next time:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">engine.resampleOnNextCall();</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_logging_in_viatra_query"><a class="link" href="#_logging_in_viatra_query">11. Logging in VIATRA Query</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>VIATRA Query logs error messages and some trace information using log4j. If you need to debug your application and would like to see these messages, you can set the log level in different hierarchy levels.
Since we use standard log4j, you can configure logging both with configuration files or through API calls.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>All loggers are children of a top-level default logger, that can be accessed from <code>ViatraQueryLoggingUtil.getDefaultLogger()</code>, just call <code>setLevel(Level.DEBUG)</code> on the returned logger to see all messages (of course you can use other levels as well).</p>
</li>
<li>
<p>Each engine has it&#8217;s own logger that is shared with the Base Index and the matchers as well. If you want to see all messages related to all engines, call <code>ViatraQueryLoggingUtil.getLogger(ViatraQueryEngine.class)</code> and set the level.</p>
</li>
<li>
<p>Some other classes also use their own loggers and the same approach is used, they get the loggers based on their class, so retrieving that logger and setting the level will work as well.</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="_configuration_problems"><a class="link" href="#_configuration_problems">11.1. Configuration problems</a></h3>
<div class="paragraph">
<p>log4j uses a properties file as a configuration for its root logger. However, since this configuration is usually supplied by developers of applications, we do not package it in VIATRA Query.
This means you may encounter the following on your console if no configuration was supplied:</p>
</div>
<div class="listingblock">
<div class="content">
<pre> log4j:WARN No appenders could be found for logger (org.eclipse.viatra.query.runtime.util.ViatraQueryLoggingUtil).
log4j:WARN Please initialize the log4j system properly.</pre>
</div>
</div>
<div class="paragraph">
<p>There are several cases where this can occur:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>You have Xtext SDK installed</strong>, which has a plugin fragment called org.eclipse.xtext.logging that supplies a log4j configuration. Make sure that the fragment is selected in your Runtime Configuration.</p>
</li>
<li>
<p><strong>You are using the tooling of VIATRA Query without the Xtext SDK</strong>, you will see the above warning, but since the patternlanguage.emf plugins also inject appenders to the loggers of VIATRA Query, log messages will be correctly displayed.</p>
</li>
<li>
<p><strong>You are using only the runtime part of VIATRA Query</strong> that has no Xtext dependency. You have to provide your own properties file (standalone execution) or fragment (OSGi execution), see <a href="http://www.eclipsezone.com/eclipse/forums/t99588.html" class="bare">http://www.eclipsezone.com/eclipse/forums/t99588.html</a></p>
</li>
<li>
<p>Alternatively, if you just want to make sure that log messages appear in the console no matter what other configuration happens, you can call <code>ViatraQueryLoggingUtil.setupConsoleAppenderForDefaultLogger()</code> which will do exactly what its name says. Since appenders and log levels are separate, you will still have to set the log level on the loggers you want to see messages from.</p>
</li>
<li>
<p>If you wish to completely turn the logger of, call <code>ViatraQueryLoggingUtil.getDefaultLogger().setLevel(Level.OFF);</code>.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<script>hljs.initHighlighting()</script>
</div>
<div class="clear"></div>
<ng-include src="'/viatra/angular/blocks/footer.html'"></ng-include>
</body>
</html>