Defining Model Queries using EMF-IncQuery
EMF-IncQuery provides an intuitive user interface to create, edit and debug queries. It assists users with various wizards, supports the editing of query definitions (patterns) in an Xtext-based editor and also provides query debugging features with the Query Explorer view.
The main components:
Wizards: there are wizards available to create EMF-IncQuery project, generator model and queries. These wizards are available under the EMF-IncQuery category when creating new resources (see the picture below)
- Query editor: the Xtext-based editor can be used to create EMF-IncQuery queries. The editor provides many features to ease the development, such as automatic code completion, validation, etc.
Query Explorer: this view can be used to apply queries on various EMF instance models. The Query Explorer can interact with EMF-based editors such as the generated tree editor, and even with GMF and Graphiti editors. Advanced querying use cases, like pattern match set filtering and detail observation is also available with the Query Explorer. The following picture presents the Pattern Editor and the Query Explorer view.
New EMF-IncQuery project
EMF-IncQuery project is the container of all EMF-IncQuery related artifacts. The wizard can be found under the EMF-IncQuery category.
New EMF-IncQuery query definition
The wizard first guides you through the creation of the query container (package) which is similar to the creation of a Java class. The second page helps you create an initial pattern within your new .eiq file. Here you can name your pattern, select the packages that you want to use in your patterns and add pattern parameters with type specification. After finishing with the wizard a new .eiq file will be created with the pattern specified on the second page.
New EMF-IncQuery generator model
If you wish to work with an EMF domain that is present as a source project in your workspace, you have to create an EMF-IncQuery generator model that will contain a reference to the .genmodel file of your EMF domain. Inside the file you must specify the resource URI of the genmodel file.
It is best to start with the built-in pattern template (available as a code completion feature). The details of the EMF-IncQuery Query Language are discussed on the language documentation page. The School example might also provide useful starting points.
Executing and debugging queries
The Query Explorer View can be used to execute and debug the queries on EMF instance models. The main features of the Query Explorer view are:
- You can load your queries into the Query Explorer by pressing the green button on the top right corner of the view. In order to apply queries to a concrete instance model, the queries have to be loaded.
EMF instance models can be loaded from EMF-based editors such as the generated or reflective EMF tree editors, GMF and Graphiti editors. There are two alternatives when loading such models:
- You can load the whole ResourceSet which is being edited by the editor (this is the default when pressing the green button)
- You can load the Resource of the selected element within the editor which can be done with the appropriate element from the view menu of the green button.
- If at least one query and instance model is loaded, the middle section of the Query Explorer will present the match sets in a tree structure. The top level element corresponds to an editor-instance model pair (because the same instance model can be loaded from different editors and the reversed way is also possible). The elements under the top level elements correspond to the queries and the low-level elements represent the match set of the given query. Note that the contents of the tree viewer are automatically updated upon changes occurring in the match sets of the pattern.
- The Pattern Registry on the left shows the loaded patterns according to the package hierarchy. It distinguishes them by their source, either coming from a generated EMF-IncQuery project from the host workspace or manually loaded ones from the runtime Eclipse. You can select and deselect single patterns or groups of patterns inside the Pattern Registry which will result the loading and unloading of queries for every instance model loaded into the Query Explorer. You can also change the way of package presentation (flat or hierarchical) in the view menu of the Query Explorer.
- Details and filter section on the right side of the view: the view of this content is based on the selection inside the tree viewer. If you select a pattern then you can specify filters on the pattern parameters (this use case is discussed later in this document). However, if you select a single match, you can observe the values of the pattern parameters which are data bound to the appropriate model elements thus automatically refreshed upon match changing. The latter use case can be influenced with the @ObservableValue annotation, which is described in depth on the Databinding documentation page.
- Almost all elements in the view provides Show Location (in the context menu) functionality which connects the element with its source. For example, if you click the Show Location on a match of a pattern, the appropriate elements will be selected in the editor which is associated to the EMF instance model. Additionally, if you click Show location on a pattern inside the Pattern Registry it will show you the pattern definition in your .eiq file.
- Patterns and instance models can be unloaded from the Query Explorer by clicking Unload model in the context menu. Additionally, if you close the editor of an instance model that is loaded into the Query Explorer, it will automatically unload it.
- Note that, modifying the contents of a .eiq file - that was loaded earlier to the Query Explorer - automatically triggers re-loading of the patterns.
Advanced use cases
Pattern Annotations supported by the Query Explorer
The IncQuery Language allows to use annotations for pattern definitions to fine-tune the behavior of a query. The following annotations are supported by the Query Explorer:
- @ObservableValue: Defines observable values for the pattern's parameters. Although it is basically used to generate accessors for such values to use in databinding contexts, the Query Explorer also presents these values. See the databinding page for detailed usage.
- @PatternUI (deprecated): Defines the label that will be used in the Query Explorer for the pattern's matches. This annotation is deprecated, please use the @QueryExplorer instead.
@QueryExplorer: The annotation can be used to define the way to present the pattern and its match set in the Query Explorer. The annotations defines the following parameters
- display (Boolean): sets whether the pattern should be displayed in the Query Explorer automatically.
- message (String): the message to be displayed for a specific match, for example "The busiest teacher $T.name$ taught the most sociable student $S.name$ in $Y.startingDate$"- from the school example. Between the '$' marks one can refer to attributes of pattern parameters that will be substituted with the concrete values during runtime.
- @OrderBy: Annotate a pattern with OrderBy to define ordering between matches displayed in the Query Explorer.
See the hover help (provided by the query editor) for more details on annotations.
In the Query Explorer you can define filters for the registered patterns. This specification is, however, instance model and pattern-specific (does not apply for the same pattern under different instance model). The aim of this facility is to narrow down the match sets of specific patterns when debugging. The following steps are required to specify a filter:
- Load an instance model and some queries into the Query Explorer.
- Select a pattern in the tree viewer. The details/filters view will be initialized for filtering.
- You can set filters for each one of the pattern parameters by clicking on the button on the right side of the text input.
- The content of the input field cannot be modified by hand for complex types - they can be selected from the popup window and only model elements from the given instance model is allowed to select. For primitive types, the value can be input directly and it is validated according to the type of the parameter.
See the following picture for an example filtering from the school example.
Settable on the EMF-IncQuery preference settings page: in wildcard mode, every aspect of the EMF model is automatically indexed, as opposed to only indexing model elements and features relevant to the currently registered patterns; thus patterns can be registered and unregistered without re-traversing the model. This is typically useful during query development. Turn off wildcard mode to decrease the memory usage while working with very large models.