blob: d2478c142aeb6e03677032d903fb9633c52b32ba [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<!--
/********************************************************************************
** Copyright (c) 2015 Obeo.
** All rights reserved. This program and the accompanying materials
** are made available under the terms of the Eclipse Public License v1.0
** which accompanies this distribution, and is available at
** http://www.eclipse.org/legal/epl-v10.html
**
** Contributors:
** Stephane Begaudeau (Obeo) - initial API and implementation
*********************************************************************************/
-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="St&eacute;phane B&eacute;gaudeau">
<!-- IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link href="../assets/css/bootstrap.css" rel="stylesheet">
<link href="../assets/css/docs.css" rel="stylesheet">
<title>Acceleo</title>
</head>
<body>
<div class="container">
<header class="jumbotron subhead" id="overview">
<!--<div class="subnav">
<ul class="nav nav-pills">
<li><a href="#introduction">Introduction</a></li>
<li><a href="#language">Language</a></li>
<li><a href="#operations">Operations</a></li>
<li><a href="#standalone">Stand Alone</a></li>
<li><a href="#migration">Migration</a></li>
<li><a href="#textproductionrules">Text Production Rules</a></li>
<li><a href="#onlineresources">Online Resources</a></li>
</ul>
</div>-->
</header>
<div class="jumbotron masthead">
<h1>Acceleo Query Language</h1>
</div>
<div class="marketing">
<h1>Query and navigate in EMF models</h1>
</div>
<section id="overview">
<div class="page-header">
<h1>Overview</h1>
</div>
<p>The Acceleo Query Language (AQL) is a language used to navigate and query an EMF model. In this document, you will find the description of all the services of the standard library of AQL.</p>
</section>
<h2 id="Introduction">Introduction</h2>
<p>
The Acceleo Query Language (AQL) is a language used to navigate and query an EMF model. In this document, you will find the description of the syntax, all the services and the standard library of AQL. <br />AQL as a query engine is small, simple, fast, extensible and it brings a richer validation
than the MTL interpreter.
</p>
<p>For those looking for a simple and fast interpreters for your EMF models, AQL can provide you with a lot of features, including:</p>
<ul>
<li>Support for static and dynamic Ecore models, no query compilation phase required.</li>
<li>The least possible overhead at evaluation time. During this phase, the evaluation goes forward and will not even try to validate or compile your expressions. Errors are tracked and captured along the way.</li>
<li>Strong validation: types are checked at validation time and the metamodels used are analyzed to do some basic type inference and avoid false positive errors.</li>
<li>Union types: In some context, a variable in a given query can have N potential types with N being often greater than one. AQL can embrace this fact without having to fall back to EObject as soon as there is more than one type.</li>
<li>A simple and straightforward implementation easily extensible with Java classes providing extension methods.</li>
<li>A very narrow dependency surface: AQL uses the very central parts of EMF, Guava and Antlr so that we could easily deploy AQL outside of Eclipse in a server or a standalone scenario.</li>
</ul>
<p>The AQL interpreter is used in Sirius with the prefix &#171;aql:&#187;.</p>
<h2 id="Syntax">Syntax</h2>
<h3 id="Basics">Basics</h3>
<p>
The syntax is very similar to the OCL syntax. An expression always starts with a variable <br />
<code>aVariable</code>
</p>
<p>
The variable named <strong>self</strong> represent the current object (think of it as the
<code>this</code>
in Java).
</p>
<p>Let&#8217;s consider the following metamodel :</p>
<p>
<img border="0" src="../assets/pics/family_ecore.png" />
</p>
<p>
From a variable one can access field or reference values using the
<code>.</code>
separator. <br />With
<code>self</code>
being an instance of <strong>Person</strong>,
<code>self.name</code>
returns the value of the attribute <strong>name</strong> and
<code>self.father</code>
return the father of the person.
</p>
<p>
If the attribute or the reference is multi-valued, then
<code>self.parents</code>
will return a collection.
</p>
<p>
Calls can be chained, as such
<code>self.parents.name</code>
will return a collection containing the names of the parents.
</p>
<p>
If one want to access the collection itself, then the separator
<code>-&gt;</code>
must be used, as such
<code>self.parents.name-&gt;size()</code>
will return the number of elements in the collection whereas
<code>self.parents.name.size()</code>
will return a collection containing <br />the sizes of each name.
</p>
<p>
AQL can also call methods modeled as EOperations or defined through Java services. The syntax denoting such a call is
<code>.</code>
for instance
<code>self.someCall()</code>
will call the <strong>someCall</strong> method and return the result.
</p>
<h3 id="Workingwithcollections">Working with collections</h3>
<p>
Filtering a collection is generaly done using either
<code>-&gt;filter(..)</code>
to keep elements of a given type or
<code>-&gt;select(..)</code>
to keep elements which are validating a given condition.
</p>
<p>
With
<code>self</code>
being an instance of <strong>Family</strong>,
<code>self.members-&gt;filter(family::Man)</code>
will return all the members of the family which are mens and
<code>self.members-&gt;select( p | p.name.startsWith('A'))</code>
will return all the members of the family which have a name starting by the letter &#8249;A&#8250;.
</p>
<p>
To access an element at a particular index you can use the operation
<code>-&gt;at(..)</code>
;
<code>self.members-&gt;at(1)</code>
will return the first person which is a member of the family (in that specific case it is probably better to use
<code>self.members-&gt;first()</code>
</p>
<p>
AQL has two kinds of collections, a
<code>Sequence</code>
which is a list, or an
<code>OrderedSet</code>
which does not allow doubles. You can convert a
<code>Sequence</code>
to an
<code>OrderedSet</code>
by as such :
<code>self.members-&gt;asSet()</code>
</p>
<p>You can also define a collection by extension using the following syntax:</p>
<ul>
<li><code>OrderedSet{self}</code> which returns a set containing the current EObject.</li>
<li><code>Sequence{self, self.eContainer()}</code> returns a sequence containing the current EObject and its parent.</li>
</ul>
<h3 id="Navigationaxes">Navigation axes</h3>
<p>AQL provides operations out of the box to browse the model. Most notably :</p>
<ul>
<li><code>self.eContainer()</code> returns the parent of the current object if there is one.</li>
<li><code>self.eAllContents(some::Type)</code> returns all direct and indirect children matching the given type.</li>
<li><code>self.eContents()</code> return all the direct children.</li>
<li><code>self.eInverse('father')</code> returns the cross reference of the reference named &#8249;father&#8250;. In this case it will return all the persons which have the current object (self) as a father.</li>
</ul>
<h3 id="Conditions">Conditions</h3>
<p>
AQL provides an <strong>If</strong> but it has to be an expression and not a statement. As such one <strong>has to define the else</strong>. Here is the syntax
</p>
<p>
<strong>if</strong>
<code>self.name.startsWith('a')</code>
<strong>then</strong>
<code>self</code>
<strong>else</strong>
<code>self.eContainer()</code>
<strong>endif</strong>
</p>
<h3 id="WalkthroughusinganUMLexample">Walkthrough using an UML example</h3>
<p>
Let&#8217;s move to a slightly more complex example to learn how to navigate through a model. We will work with a model instance from the following metamodel: a simplified view of the UML2 metamodel with <strong>Package</strong>, <strong>UseCase</strong>, <strong>Model</strong> or <strong>Component</strong>
instances.
</p>
<p>
<img border="0" src="../assets/pics/simple-uml-ecore.jpg" />
</p>
<p>
The following illustration demonstrate the result of the just typing
<code>self</code>
as a query. At the bottom every instance of the UML model is represented by a node with containment relationships from top to bottom and displaying the non-contained references in between those nodes through horizontal edges. The result of the query is highlighted in <strong>blue</strong>.
</p>
<p>
<img border="0" src="../assets/pics/self.jpg" />
</p>
<p>
The variable <strong>self</strong> here is the <strong>Class</strong> named &#171;Invoice&#187; in the model, as such the query
<code>self</code>
hightlight this instance.
</p>
<h4 id="eContainer">eContainer()</h4>
<p>
<img border="0" src="../assets/pics/self-econtainer.jpg" />
</p>
<p>
When using the query
<code>self.eContainer()</code>
the cursor move from the
<code>self</code>
variable to its most direct parent, here the <strong>Component</strong> instance named &#171;Accounting&#187;.
</p>
<p>
<img border="0" src="../assets/pics/self-econtainer-econtainer.jpg" />
</p>
<p>
Such calls can be chained and as such
<code>self.eContainer().eContainer()</code>
return the <strong>Component</strong> parents: the <strong>Package</strong> named &#171;Components&#187;.
</p>
<p>
<img border="0" src="../assets/pics/self-econtainer-model.jpg" />
</p>
<p>
The
<code>eContainer()</code>
call can also be used with a type parameter, in that case it will be transitively executed up to the point where an instance of the given type is found.
</p>
<p>
In this case then
<code>self.eContainer(uml::Model)</code>
goes up to the root of the graph. If no instance of the given type is found in the parents then the query returns an empty result.
</p>
<p>
<img border="0" src="../assets/pics/self-econtainer-class.jpg" />
</p>
<p>
<code>eContainer()</code>
or any other service using types as parameters will match both the given types or its subtypes. The only exception to this rule is the
<code>oclIsTypeOf(..)</code>
service which is intended to check only for the given type and not its subtypes.
</p>
<p>
When using the query
<code>self.eContainer(uml::Class)</code>
the result is an instance of <strong>Component</strong> as the <strong>Component</strong> type extends <strong>Class</strong> in the metamodel.
</p>
<p>
<img border="0" src="../assets/pics/self-econtainerorself.jpg" />
</p>
<p>
A variant of
<code>eContainer(..)</code>
named
<code>eContainerOrSelf(..)</code>
is provided it will first check the type of the current instance. As such the query
<code>self.eContainerOrSelf(uml::Class)</code>
when <strong>self</strong> is the &#171;Invoice&#187; class returns this instance.
</p>
<h4 id="eContents">eContents()</h4>
<p>
<img border="0" src="../assets/pics/self-econtents.jpg" />
</p>
<p>
One use
<code>eContainer()</code>
to go up in the parent. The
<code>eContents()</code>
axes is its counterpart and returns the direct children of the element.
</p>
<h4 id="select">select()</h4>
<p>
<img border="0" src="../assets/pics/self-econtents-select-name-id.jpg" />
</p>
<p>
The
<code>select(...)</code>
service can be used to filter elements from a list by veryfing a predicate. In the query
<code>self.eContents()-&gt;select(p | p.name = 'id')</code>
the query only returns the elements which have a name equal to <strong>"id"</strong>, in this case a single element.
</p>
<p>
<img border="0" src="../assets/pics/self-econtents-select-name-notid.jpg" />
</p>
<p>
Equality is checked with a single
<code>=</code>
, inequality is expressed with the operator
<code>&lt;&gt;</code>
.
</p>
<p>
<img border="0" src="../assets/pics/self-econtents-select-visibility.jpg" />
</p>
<p>
Comparing values with an enumeration is slightly different as the enumeration value should be explicitely qualified. In the
<code>self.eContents()-&gt;select(p | p.visibility = uml::VisibilityKind::private )</code>
query the expression
<code>uml::VisibilityKind::private</code>
denotes the enumeration literal named <strong>private</strong> which is contained in the <strong>VisibilityKind</strong> enumeration of the <strong>uml</strong> metamodel.
</p>
<h4 id="eAllContents">eAllContents()</h4>
<p>
<img border="0" src="../assets/pics/self-econtainer-model-eallcontents.jpg" />
</p>
<p>
The
<code>eAllContents()</code>
axe is used to browse direct and indirect children. It goes from the starting point to the leafs of the model. Here the expression starts with
<code>self.eContainer(uml::Model)</code>
which has we&#8217;ve seen before goes up until an instance of <strong>Model</strong> is found. From here
<code>eAllContents</code>
is executed returning all the direct and indirect childrens of the &#171;Travel Agency&#187; <strong>model</strong> instance.
</p>
<p>
<img border="0" src="../assets/pics/econtainer-eallcontents-select-name-startswith.jpg" />
</p>
<p>Just like any other collection it can be filtered to retrieve, for instace, the elements whose name is starting by the letter &#171;I&#187;.</p>
<p>
<img border="0" src="../assets/pics/self-econtainer-model-eallcontents-components.jpg" />
</p>
<p>
A type parameter can be used to retrieve the direct or indirect children of a specific type: here <strong>components</strong>.
</p>
<p>
<img border="0" src="../assets/pics/self-econtainer-model-eallcontents-usecases.jpg" />
</p>
<p>
Or <strong>use case</strong> instances.
</p>
<p>
<img border="0" src="../assets/pics/self.econtainer-model-eallcontents-multipletypes.jpg" />
</p>
<p>It is interesting to note that the parameter can also be a collection of types, enabling the retrieval of many elements through a single pass.</p>
<h4 id="eInverse">eInverse()</h4>
<p>
Queries using
<code>eAllContents</code>
must be designed with care as they tend to lead to an intense browsing of the model. In many cases they can be replaced with
<code>eInverse()</code>
calls to retrieve elements of interests.
</p>
<p>
<img border="0" src="../assets/pics/self-econtainer-einverse.jpg" />
</p>
<p>
<code>eInverse()</code>
returns any element which as a relationship with the current one. This relationship can be indifferently a containment one or not.
</p>
<p>
<img border="0" src="../assets/pics/econtainer-einverse-usecase.jpg" />
</p>
<p>
It is often of interest to restrict the type of elements we expect out of the
<code>eInverse()</code>
call. With the query
<code>self.eContainer().eInverse(uml::UseCase)</code>
only use cases instances will be returned, here the <strong>UseCase</strong> named &#171;to Invoice&#187; which refers to the &#171;Accounting&#187; <strong>Component</strong> through the reference named <strong>subject</strong>
</p>
<p>
<img border="0" src="../assets/pics/self-econtainer-einverse-packagedelement.jpg" />
</p>
<p>
One can also be even more explicit and query for a specific reference name, here
<code>packagedElement</code>
: only the <strong>Package</strong> named &#171;Components&#187; refers to the &#171;Accounting&#187; <strong>Component</strong> through the reference named &#171;packagedElement&#187;.
</p>
<h2 id="LanguageReference">Language Reference</h2>
<p>These sections are listing all the services of the standard library of AQL.</p>
<section id="services">
<div class="page-header">
<h3>Services available for all types</h3>
</div>
<h3>String + Object : String</h3>
<p>Returns the concatenation of the current string and the given object "any" (as a String).</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'times ' + 42</td>
<td>'times 42'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Object + String : String</h3>
<p>Returns the concatenation of self (as a String) and the given string "s".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>42 + ' times'</td>
<td>'42 times'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Object <> Object : Boolean</h3>
<p>Indicates whether the object "o1" is a different object from the object "o2".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello' <> 'World'</td>
<td>true</td>
</tr>
<tr>
<td>'Hello' <> 'Hello'</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Object = Object : Boolean</h3>
<p>Indicates whether the object "o1" i"the same as the object "o2". For more information refer to the Object#equals(Object) method.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello' = 'World'</td>
<td>false</td>
</tr>
<tr>
<td>'Hello' = 'Hello'</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Object.oclAsType(Object) : Object</h3>
<p>Casts the current object to the given type.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.oclAsType(ecore::EPackage)</td>
<td>anEPackage</td>
</tr>
<tr>
<td>anEPackage.oclAsType(ecore::EClass)</td>
<td>anEPackage</td>
</tr>
</tbody>
</table>
<p>Contrary to Acceleo 3, the type is ignored, the given object will be returned directly.</p>
<h4>In other languages</h4>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>anEPackage.oclAsType(ecore::EPackage)</td>
<td>anEPackage</td>
</tr>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>anEPackage.oclAsType(ecore::EClass)</td>
<td>oclInvalid</td>
</tr>
</tbody>
</table>
<hr />
<h3>Object.oclIsKindOf(Object) : Boolean</h3>
<p>Evaluates to "true" if the type of the object o1 conforms to the type "classifier". That is, o1 is of type "classifier" or a subtype of "classifier".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.oclIsKindOf(ecore::EPackage)</td>
<td>true</td>
</tr>
<tr>
<td>anEPackage.oclIsKindOf(ecore::ENamedElement)</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Object.oclIsTypeOf(Object) : Boolean</h3>
<p>Evaluates to "true" if the object o1 if of the type "classifier" but not a subtype of the "classifier".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.oclIsKindOf(ecore::EPackage)</td>
<td>true</td>
</tr>
<tr>
<td>anEPackage.oclIsKindOf(ecore::ENamedElement)</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Object.toString() : String</h3>
<p>Returns a string representation of the current object.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>42.toString()</td>
<td>'42'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Object.trace() : String</h3>
<p>Returns a string representation of the current environment.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>42.trace()</td>
<td>'Metamodels: http://www.eclipse.org/emf/2002/Ecore Services: org.eclipse.acceleo.query.services.AnyServices public java.lang.String org.eclipse.acceleo.query.services.AnyServices.add(java.lang.Object,java.lang.String) ... receiver: 42 '</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
</section>
<section id="services">
<div class="page-header">
<h3>Services available for Booleans</h3>
</div>
<h3>Boolean.and(Boolean) : Boolean</h3>
<p>Logical and.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>true and false</td>
<td>false</td>
</tr>
<tr>
<td>false and true</td>
<td>false</td>
</tr>
<tr>
<td>true and true</td>
<td>true</td>
</tr>
<tr>
<td>false and false</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Boolean.implies(Boolean) : Boolean</h3>
<p>Logical implies.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>true implies true</td>
<td>true</td>
</tr>
<tr>
<td>true implies false</td>
<td>false</td>
</tr>
<tr>
<td>false implies true</td>
<td>true</td>
</tr>
<tr>
<td>false implies false</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Boolean.not() : Boolean</h3>
<p>Logical negation.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>not true</td>
<td>false</td>
</tr>
<tr>
<td>not false</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Boolean.or(Boolean) : Boolean</h3>
<p>Logical or.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>true or false</td>
<td>true</td>
</tr>
<tr>
<td>false or true</td>
<td>true</td>
</tr>
<tr>
<td>true or true</td>
<td>true</td>
</tr>
<tr>
<td>false or false</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Boolean.xor(Boolean) : Boolean</h3>
<p>Logical xor.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>true xor true</td>
<td>false</td>
</tr>
<tr>
<td>true xor false</td>
<td>true</td>
</tr>
<tr>
<td>false xor true</td>
<td>true</td>
</tr>
<tr>
<td>false xor false</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
</section>
<section id="services">
<div class="page-header">
<h3>Services available for Collections</h3>
</div>
<h3>OrderedSet + Collection : OrderedSet</h3>
<p>Returns the concatenation of the given collection into the current set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'} + OrderedSet{'c', 'b', 'f'}</td>
<td>OrderedSet{'a', 'b', 'c', 'c', 'b', 'f'}</td>
</tr>
</tbody>
</table>
<p>The service addAll has been replaced by "add" in order to have access to the operator "+" between to sets</p>
<h4>In other languages</h4>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>OrderedSet{'a', 'b', 'c'}.addAll(OrderedSet{'c', 'b', 'f'})</td>
<td>OrderedSet{'a', 'b', 'c', 'c', 'b', 'f'}</td>
</tr>
</tbody>
</table>
<hr />
<h3>Sequence + Collection : Sequence</h3>
<p>Returns the concatenation of the given collection into the given sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}.add(Sequence{'d', 'e'})</td>
<td>Sequence{'a', 'b', 'c', 'd', 'e'}</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'} + OrderedSet{'c', 'e'}</td>
<td>Sequence{'a', 'b', 'c', 'c', 'e'}</td>
</tr>
</tbody>
</table>
<p>The service addAll has been replaced by "add" in order to have access to the operator "+" between to sequences</p>
<h4>In other languages</h4>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>Sequence{'a', 'b', 'c'} + Sequence{'d', 'e'}</td>
<td>Sequence{'a', 'b', 'c', 'd', 'e'}</td>
</tr>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>Sequence{'a', 'b', 'c'}.addAll(OrderedSet{'c', 'e'})</td>
<td>Sequence{'a', 'b', 'c', 'c', 'e'}</td>
</tr>
</tbody>
</table>
<hr />
<h3>Collection->any( x | ... ) : Object</h3>
<p>Gets the first element in the current collection for which the value returned by the lambda evaluates to "true".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->any(str | str.size() = 1)</td>
<td>'a'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->asOrderedSet() : OrderedSet</h3>
<p>Returns a set representation of the specified collection. Returns the same object if it is a set already. This operation has the same behavior as "asSet()"</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->asOrderedSet()</td>
<td>OrderedSet{'a', 'b', 'c'}</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->asOrderedSet()</td>
<td>OrderedSet{'a', 'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->asSequence() : Sequence</h3>
<p>Returns a sequence representation of the specified collection. Returns the same object if it is already a sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->asSequence()</td>
<td>Sequence{'a', 'b', 'c'}</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->asSequence()</td>
<td>Sequence{'a', 'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->asSet() : OrderedSet</h3>
<p>Returns a set representation of the specified collection. Returns the same object if it is already a set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->asSet()</td>
<td>OrderedSet{'a', 'b', 'c'}</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c', 'c', 'a'}->asSet()</td>
<td>OrderedSet{'a', 'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->at(Integer) : Object</h3>
<p>Returns the element at the specified position in the sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->at(1)</td>
<td>'a'</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->at(2)</td>
<td>'b'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->collect( x | ... ) : Sequence{Object}</h3>
<p>Returns a sequence containing the result of applying "lambda" on all elements contained in the current sequence, maintaining order.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->collect(str | str.toUpper())</td>
<td>Sequence{'A', 'B', 'C'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->collect( x | ... ) : OrderedSet{Object}</h3>
<p>Returns a set containing the result of applying "lambda" on all elements contained in the current set, maintaining order.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->collect(str | str.toUpper())</td>
<td>OrderedSet{'A', 'B', 'C'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->concat(Collection) : OrderedSet</h3>
<p>Returns the concatenation of the current set with the given collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}.concat(Sequence{'d', 'e'})</td>
<td>OrderedSet{'a', 'b', 'c', 'd', 'e'}</td>
</tr>
</tbody>
</table>
<p></p>
<h4>In other languages</h4>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>OrderedSet{'a', 'b', 'c'}.addAll(Sequence{'d', 'e'})</td>
<td>OrderedSet{'a', 'b', 'c', 'd', 'e'}</td>
</tr>
</tbody>
</table>
<hr />
<h3>Sequence->concat(Collection) : Sequence</h3>
<p>Returns the concatenation of the current sequence with the given collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}.concat(Sequence{'d', 'e'})</td>
<td>Sequence{'a', 'b', 'c', 'd', 'e'}</td>
</tr>
</tbody>
</table>
<p></p>
<h4>In other languages</h4>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>Sequence{'a', 'b', 'c'}.addAll(Sequence{'d', 'e'})</td>
<td>Sequence{'a', 'b', 'c', 'd', 'e'}</td>
</tr>
</tbody>
</table>
<hr />
<h3>OrderedSet->count(Object) : Integer</h3>
<p>Returns "1" if the current set contains the given object, "0" otherwise.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->count('d')</td>
<td>0</td>
</tr>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->count('a')</td>
<td>1</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence{Object}->count(Object) : Integer</h3>
<p>Counts the number of occurrences of the given object in the given sequence</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->count('d')</td>
<td>0</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->count('a')</td>
<td>1</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->excludes(Object) : Boolean</h3>
<p>Indicates if the given collection doesn't contain the given object.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->excludes('a')</td>
<td>false</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->excludes('d')</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->excludesAll(Collection) : Boolean</h3>
<p>Indicates if no elements from the second collection are contained in the first collection</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b'}->excludesAll(OrderedSet{'f'})</td>
<td>true</td>
</tr>
<tr>
<td>Sequence{'a', 'b'}->excludesAll(OrderedSet{'a', 'f'})</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->excluding(Object) : OrderedSet</h3>
<p>Removes the given object from the current set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->excluding('c')</td>
<td>OrderedSet{'a', 'b'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->excluding(Object) : Sequence</h3>
<p>Removes the given object from the current sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->excluding('c')</td>
<td>Sequence{'a', 'b'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->exists( x | ... ) : Boolean</h3>
<p>Indicates if it exists an object from the given collection for which the given lambda evaluates to "true"</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->exists(str | str.size() > 5)</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->filter(EClassifier) : OrderedSet</h3>
<p>Keeps only instances of the given EClassifier from the given set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{anEClass, anEAttribute, anEReference}->filter(ecore::EClass)</td>
<td>OrederedSet{anEClass}</td>
</tr>
<tr>
<td>OrderedSet{anEClass, anEAttribute}->filter(ecore::EStructuralFeature)</td>
<td>OrederedSet{anEAttribute}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->filter(OrderedSet{EClassifier}) : Sequence</h3>
<p>Keeps only instances of the given EClassifier in the given sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{anEClass, anEAttribute, anEReference}->filter({ecore::EClass | ecore::EReference})</td>
<td>Sequence{anEClass, anEReference}</td>
</tr>
<tr>
<td>Sequence{anEClass, anEAttribute, anEPackage}->filter({ecore::EStructuralFeature | ecore::EPacakge})</td>
<td>Sequence{anEAttribute, anEPackage}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->filter(OrderedSet{EClassifier}) : OrderedSet</h3>
<p>Keeps only instances of the given set of EClassifier from the given set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{anEClass, anEAttribute, anEReference}->filter({ecore::EClass | ecore::EReference})</td>
<td>OrderedSet{anEClass, anEReference}</td>
</tr>
<tr>
<td>OrderedSet{anEClass, anEAttribute, anEPackage}->filter({ecore::EStructuralFeature | ecore::EPacakge})</td>
<td>OrderedSet{anEAttribute, anEPackage}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->filter(EClassifier) : Sequence</h3>
<p>Keeps only instances of the given EClassifier in the given sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{anEClass, anEAttribute, anEReference}->filter(ecore::EClass)</td>
<td>Sequence{anEClass}</td>
</tr>
<tr>
<td>Sequence{anEClass, anEAttribute}->filter(ecore::EStructuralFeature)</td>
<td>Sequence{anEAttribute}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->first() : Object</h3>
<p>Returns the first element of the specified Collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->first()</td>
<td>'a'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->forAll( x | ... ) : Boolean</h3>
<p>Indicates if all the objects from the given collection validate the given lamba</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'ccc'}->forAll(str | str.size() = 1)</td>
<td>false</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->forAll(str | str.size() = 1)</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->includes(Object) : Boolean</h3>
<p>Indicates if the given collection contains the given object.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->includes('a')</td>
<td>true</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->includes('d')</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->includesAll(Collection) : Boolean</h3>
<p>Indicates if all elements from the second collection are contained in the first collection</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->includesAll(OrderedSet{'a'})</td>
<td>true</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'}->includesAll(OrderedSet{'a', 'f'})</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->including(Object) : OrderedSet</h3>
<p>Adds the given object to the current set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->including('d')</td>
<td>OrderedSet{'a', 'b', 'c', 'd'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->including(Object) : Sequence</h3>
<p>Adds the given object to the current sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->including('d')</td>
<td>Sequence{'a', 'b', 'c', 'd'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->indexOf(Object) : Integer</h3>
<p>Returns the index of the given object in the given set ([1..size]).</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{1, 2, 3, 4}->indexOf(3)</td>
<td>3</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->indexOf(Object) : Integer</h3>
<p>Returns the index of the given object in the given sequence ([1..size]).</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{1, 2, 3, 4}->indexOf(3)</td>
<td>3</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->insertAt(Integer, Object) : OrderedSet</h3>
<p>Inserts the given object in a copy of the given set at the given position ([1..size]). If the given set already contains this object, it will be moved to the accurate position.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->insertAt(2, 'f')</td>
<td>Sequence{'a', 'f', 'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->insertAt(Integer, Object) : Sequence</h3>
<p>Inserts the given object in a copy of the given sequence at the given position ([1..size]).</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->insertAt(2, 'f')</td>
<td>Sequence{'a', 'f', 'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->intersection(Collection) : OrderedSet</h3>
<p>Creates a set with the elements from the given set that are also present in the given collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->intersection(OrderedSet{'a', 'f'})</td>
<td>OrderedSet{'a'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->intersection(Collection) : Sequence</h3>
<p>Creates a sequence with elements from the given sequence that are present in both the current sequence and the given other {@code Collection}. Iteration order will match that of the current sequence. Duplicates from the first list will all be kept in the result if they also are in the
second one, but duplicates from the second list will be dumped even if they are present in the first.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->intersection(OrderedSet{'a', 'f'})</td>
<td>Sequence{'a'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->isEmpty() : Boolean</h3>
<p>Returns "true" when the input collection is empty.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->isEmpty()</td>
<td>false</td>
</tr>
<tr>
<td>Sequence{}->isEmpty()</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->isUnique( x | ... ) : Boolean</h3>
<p>Indicates if the evaluation of the given lambda gives a different value for all elements of the given collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->isUnique(str | str.size())</td>
<td>false</td>
</tr>
<tr>
<td>Sequence{'a', 'bb', 'ccc'}->isUnique(str | str.size())</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->last() : Object</h3>
<p>Returns the last element of the given sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->last()</td>
<td>'c'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->last() : Object</h3>
<p>Returns the last element of the given set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->last()</td>
<td>'c'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->notEmpty() : Boolean</h3>
<p>Returns "true" when the input collection is not empty.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->notEmpty()</td>
<td>true</td>
</tr>
<tr>
<td>Sequence{}->notEmpty()</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->one( x | ... ) : Boolean</h3>
<p>Indicates if one and only one element of the given collection validates the given lambda.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->one(str | str.equals('a'))</td>
<td>true</td>
</tr>
<tr>
<td>Sequence{'a', 'a', 'c'}->one(str | str.equals('a'))</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->prepend(Object) : OrderedSet</h3>
<p>Inserts the given object in a copy of the given set at the first position. If the set already contained the given object, it is moved to the first position.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->prepend('f')</td>
<td>OrderedSet{'f', 'a', 'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->prepend(Object) : Sequence</h3>
<p>Inserts the given object in a copy of the given sequence at the first position.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->prepend('f')</td>
<td>Sequence{'f', 'a', 'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->reject( x | ... ) : OrderedSet</h3>
<p>Reject returns a filtered version of the specified set. Only elements for which the given "lambda" evaluates to false will be present in the returned set</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->reject(str | str.equals('a'))</td>
<td>OrderedSet{'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->reject( x | ... ) : Sequence</h3>
<p>Reject returns a filtered version of the specified sequence. Only elements for which the given "lambda" evaluates to false will be present in the returned sequence</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->reject(str | str.equals('a'))</td>
<td>Sequence{'b', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->reverse() : OrderedSet</h3>
<p>Returns the given set in reversed order.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->reverse()</td>
<td>OrderedSet{'c', 'b', 'a'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->reverse() : Sequence</h3>
<p>Returns the given sequence in reversed order.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->reverse()</td>
<td>Sequence{'c', 'b', 'a'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->select( x | ... ) : Sequence</h3>
<p>Select returns a filtered version of the specified sequence. Only elements for which the given "lambda" evaluates to true will be present in the returned sequence.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->select(str | str.equals('a'))</td>
<td>Sequence{'a'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->select( x | ... ) : OrderedSet</h3>
<p>Select returns a filtered version of the specified set. Only elements for which the given "lambda" evaluates to true will be present in the returned set.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->select(str | str.equals('a'))</td>
<td>OrderedSet{'a'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->sep(Object, Object, Object) : Sequence{Object}</h3>
<p>Inserts the given separator between each elements of the given collection, the given prefix before the first element, and the given suffix after the last element.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->sep('[', '-', ']')</td>
<td>Sequence{'[', 'a', '-', 'b', '-', 'c', ']'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->sep(Object) : Sequence{Object}</h3>
<p>Inserts the given separator between each elements of the given collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->sep('-')</td>
<td>Sequence{'a', '-', 'b', '-', 'c'}</td>
</tr>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->sep('-')</td>
<td>Sequence{'a', '-', 'b', '-', 'c'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->size() : Integer</h3>
<p>Returns the size of the specified collection</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->size()</td>
<td>3</td>
</tr>
<tr>
<td>OrderedSet{'a', 'b', 'c', 'd'}->size()</td>
<td>4</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->sortedBy( x | ... ) : Sequence</h3>
<p>Returns a sequence containing the elements of the original sequence ordered by the result of the given lamba</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'aa', 'bbb', 'c'}->sortedBy(str | str.size())</td>
<td>Sequence{'c', 'aa', 'bbb'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->sortedBy( x | ... ) : OrderedSet</h3>
<p>Returns a set containing the elements of the original set ordered by the result of the given lamba</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'aa', 'bbb', 'c'}->sortedBy(str | str.size())</td>
<td>OrderedSet{'c', 'aa', 'bbb'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence - Collection : Sequence</h3>
<p>Returns the difference of the current sequence and the given collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'} - Sequence{'c', 'b', 'f'}</td>
<td>Sequence{'a'}</td>
</tr>
<tr>
<td>Sequence{'a', 'b', 'c'} - OrderedSet{'c', 'b', 'f'}</td>
<td>Sequence{'a'}</td>
</tr>
</tbody>
</table>
<p>The service removeAll has been replaced by "sub" in order to have access to the operator "-" between to sequences</p>
<h4>In other languages</h4>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>Sequence{'a', 'b', 'c'}.removeAll(Sequence{'c', 'b', 'f'})</td>
<td>Sequence{'a'}</td>
</tr>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>Sequence{'a', 'b', 'c'}.removeAll(OrderedSet{'c', 'b', 'f'})</td>
<td>Sequence{'a'}</td>
</tr>
</tbody>
</table>
<hr />
<h3>OrderedSet - Collection : OrderedSet</h3>
<p>Returns the difference of the current set and the given collection.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'} - OrderedSet{'c', 'b', 'f'}</td>
<td>OrderedSet{'a'}</td>
</tr>
</tbody>
</table>
<p>The service removeAll has been replaced by "sub" in order to have access to the operator "-" between to sets</p>
<h4>In other languages</h4>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Acceleo 3 (MTL)</td>
<td>OrderedSet{'a', 'b', 'c'}.removeAll(OrderedSet{'c', 'b', 'f'})</td>
<td>OrderedSet{'a'}</td>
</tr>
</tbody>
</table>
<hr />
<h3>OrderedSet->subOrderedSet(Integer, Integer) : OrderedSet</h3>
<p>Returns a subset of the given set</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->subOrderedSet(1, 2)</td>
<td>OrderedSet{'a', 'b'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->subSequence(Integer, Integer) : Sequence</h3>
<p>Returns a subset of the given sequence</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->subSequence(1, 2)</td>
<td>Sequence{'a', 'b'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Collection->sum() : Number</h3>
<p>Sums elements of the given collection if possible.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{1, 2, 3, 4}->sum()</td>
<td>10</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Sequence->union(Sequence) : Sequence</h3>
<p>Returns a sequence containing all the elements of the first and second sequences</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>Sequence{'a', 'b', 'c'}->union(Sequence{'d', 'c'})</td>
<td>Sequence{'a', 'b', 'c', 'd'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>OrderedSet->union(OrderedSet) : OrderedSet</h3>
<p>Returns a set containing all the elements of the first and second sets</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>OrderedSet{'a', 'b', 'c'}->union(OrderedSet{'d', 'c'})</td>
<td>OrderedSet{'a', 'b', 'c', 'd'}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
</section>
<section id="services">
<div class="page-header">
<h3>Services available for Comparables</h3>
</div>
<h3>Comparable > Comparable : Boolean</h3>
<p>Compares "a" to "b" and return "true" if "a" is greater than "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello' > 'Abc'</td>
<td>true</td>
</tr>
<tr>
<td>'Hello' > 'Hello'</td>
<td>false</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Comparable >= Comparable : Boolean</h3>
<p>Compares "a" to "b" and return "true" if "a" is greater than or equal to "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello' >= 'Abc'</td>
<td>true</td>
</tr>
<tr>
<td>'Hello' >= 'Hello'</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Comparable < Comparable : Boolean</h3>
<p>Compares "a" to "b" and return "true" if "a" is less than "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello' < 'Hello'</td>
<td>false</td>
</tr>
<tr>
<td>'Hello' < 'World'</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>Comparable <= Comparable : Boolean</h3>
<p>Compares "a" to "b" and return "true" if "a" is less than or equal to "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello' <='Hello'</td>
<td>true</td>
</tr>
<tr>
<td>'Hello' <='World'</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
</section>
<section id="services">
<div class="page-header">
<h3>Services available for EObjects</h3>
</div>
<h3>EClass.allInstances() : Sequence{EObject}</h3>
<p>Returns all instances of the EClass</p>
<hr />
<h3>OrderedSet{EClass}->allInstances() : Sequence{EObject}</h3>
<p>Returns all instances of any EClass from the OrderedSet</p>
<hr />
<h3>EObject.eAllContents() : Sequence{EObject}</h3>
<p>Returns a sequence of the EObjects recursively contained in the specified root eObject.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.eAllContents()</td>
<td>Sequence{firstEClass, firstEAttribute, secondEClass, firstDataType}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eAllContents(OrderedSet{EClass}) : Sequence{EObject}</h3>
<p>Returns a sequence of the EObjects recursively contained in the specified root eObject and that are instances of the specified EClass</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.eAllContents({ecore::EPackage | ecore::EClass})</td>
<td>Sequence{ePackage, eClass, ...}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eAllContents(EClass) : Sequence{EObject}</h3>
<p>Returns a sequence of the EObjects recursively contained in the specified root eObject and that are instances of the specified EClass</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.eAllContents(ecore::EClass)</td>
<td>Sequence{firstEClass, secondEClass}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eClass() : EClass</h3>
<p>Returns the EClass of the specified EObject</p>
<hr />
<h3>EObject.eContainer() : EObject</h3>
<p>Returns the container of the specified EObject</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>firstEAttribute.eContainer()</td>
<td>firstEClass</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eContainer(EClass) : EObject</h3>
<p>Returns the first container of the specified EObject that matches the given type</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>firstEAttribute.eContainer(ecore::EPackage)</td>
<td>anEPackage</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eContainerOrSelf(EClass) : EObject</h3>
<p>Returns self or the first container of the specified EObject that matches the given type</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>firstEAttribute.eContainerOrSelf(ecore::EAttribute)</td>
<td>firstEAttribute</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eContainingFeature() : EStructuralFeature</h3>
<p>Returns the containing feature of the specified EObject</p>
<hr />
<h3>EObject.eContainmentFeature() : EReference</h3>
<p>Returns the containment feature of the specified EObject</p>
<hr />
<h3>EObject.eContents() : Sequence{EObject}</h3>
<p>Returns the contents of the specified EObject instance.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.eContents()</td>
<td>Sequence{firstEClass, secondEClass, firstDataType}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eContents(EClass) : Sequence{EObject}</h3>
<p>Returns a sequence made of the instances of the specified type in the contents of the specified eObject.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.eContents(ecore::EDataType)</td>
<td>Sequence{firstDataType}</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eContents(OrderedSet{EClass}) : Sequence{EObject}</h3>
<p>Returns a sequence made of the instances of the specified types in the contents of the specified eObject.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>anEPackage.eContents({ecore::EPackage | ecore::EClass})</td>
<td>Sequence{SubEPackage, eClass, ... }</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>EObject.eCrossReferences() : Object</h3>
<p>Returns the list of all EObjects cross-referenced from the receiver.</p>
<hr />
<h3>EObject.eGet(String) : Object</h3>
<p>Handles calls to the operation "eGet". This will fetch the value of the feature named "featureName" on "source"</p>
<hr />
<h3>EObject.eInverse() : OrderedSet{EObject}</h3>
<p>Returns the set containing the inverse references.</p>
<hr />
<h3>EObject.eInverse(EClassifier) : OrderedSet{EObject}</h3>
<p>Returns the elements of the given type from the set of the inverse references of the receiver.</p>
<hr />
<h3>EObject.eInverse(String) : OrderedSet{EObject}</h3>
<p>Returns the elements from the set of the inverse references of the receiver that are referencing the receiver using a feature with the given name.</p>
<hr />
</section>
<section id="services">
<div class="page-header">
<h3>Services available for Resources and URIs</h3>
</div>
<h3>EObject.eResource() : Resource</h3>
<p>Returns the Resource containing the given EObject. This service is equivalent to a direct call to EObject#eResource().</p>
<hr />
<h3>URI.fileExtension() : String</h3>
<p>Returns the extension of the file referred to by the given URI. This service is equivalent to a direct call to URI#fileExtension()</p>
<hr />
<h3>Resource.getContents() : Sequence{EObject}</h3>
<p>Returns the direct content of the given Resource. This service is equivalent to a direct call to Resource#getContents()</p>
<hr />
<h3>Resource.getContents(EClass) : Sequence{EObject}</h3>
<p>Returns the EObjects of the given type from the direct content of the given Resource.</p>
<hr />
<h3>Resource.getURI() : URI</h3>
<p>Returns the URI of the given Resource. This service is equivalent to a direct call to Resource#getURI()</p>
<hr />
<h3>URI.isPlatformPlugin() : Boolean</h3>
<p>Returns "true" if the given URI is a platform plugin URI. This service is equivalent to a direct call to URI#isPlatformPlugin()</p>
<hr />
<h3>URI.isPlatformResource() : Boolean</h3>
<p>Returns "true" if the given URI is a platform resource URI. This service is equivalent to a direct call to URI#isPlatformResource()</p>
<hr />
<h3>URI.lastSegment() : String</h3>
<p>Returns the last segment of the given URI. This service is equivalent to a direct call to URI#lastSegment()</p>
<hr />
</section>
<section id="services">
<div class="page-header">
<h3>Services available for Strings</h3>
</div>
<h3>String + String : String</h3>
<p>Returns a string that is the result of the concatenation of the current string and the string "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello' + 'World'</td>
<td>HelloWorld</td>
</tr>
</tbody>
</table>
<p>This operation behaves like '+' between two strings.</p>
<hr />
<h3>String.concat(String) : String</h3>
<p>Returns a string that is the result of the concatenation of the current string and the string "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello'.concat('World')</td>
<td>HelloWorld</td>
</tr>
</tbody>
</table>
<p>This operation behaves like '+' between two strings.</p>
<hr />
<h3>String.contains(String) : Boolean</h3>
<p>Returns "true" if the current String contains the String "b"</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello'.contains('llo')</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.endsWith(String) : Boolean</h3>
<p>Returns true if the current String ends with the string "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello'.endsWidth('llo')</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.equalsIgnoreCase(String) : Boolean</h3>
<p>Returns true if the current String is equals to the String "b" without considering case in the comparison.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello'.equalsIgnoreCase('hello')</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.first(Integer) : String</h3>
<p>Returns the "n" first characters of the current String, or the current String itself if its size is less than "n".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.first(5)</td>
<td>'Hello'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.index(String) : Integer</h3>
<p>Returns the index of the first occurrence "subString" in the current String, or -1 if "subString" is not in the current String. The index referential is 1 as in OCL and not 0.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloHello'.index('Hello')</td>
<td>1</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.index(String, Integer) : Integer</h3>
<p>Returns the index of the first occurrence "subString" in the current String from the given index, or -1 if "subString" is not in the current String. The index referential is 1 as in OCL and not 0.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloHello'.index('Hello', 2)</td>
<td>6</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.isAlpha() : Boolean</h3>
<p>Returns "true" if self consists only of alphabetical characters, "false" otherwise.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'abc123'.isAlpha()</td>
<td>false</td>
</tr>
<tr>
<td>'abcdef'.isAlpha()</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.isAlphaNum() : Boolean</h3>
<p>Returns "true" if self consists only of alphanumeric characters, "false" otherwise.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'abc123'.isAlphaNum()</td>
<td>true</td>
</tr>
<tr>
<td>'abcdef'.isAlphaNum()</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.last(Integer) : String</h3>
<p>Returns the "n" last characters of the current String, or the current String if its size is less than "n".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.last(5)</td>
<td>'World'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.lastIndex(String, Integer) : Integer</h3>
<p>Returns the index of the last occurrence "subString" in the current String searching backward from the given index, or -1 if "subString" is not in the current String. The index referential is 1 as in OCL and not 0.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloHello'.lastIndex('Hello', 7)</td>
<td>1</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.lastIndex(String) : Integer</h3>
<p>Returns the index of the last occurrence of "subString" in the current String, "-1" if the current String doesn't contain this particular substring. The index referential is 1 as in OCL and not 0.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloHello'.lastIndex('World')</td>
<td>6</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.matches(String) : Boolean</h3>
<p>Returns "true" if the current String matches the given "regex".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello'.matches('*llo')</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.prefix(String) : String</h3>
<p>Returns the current String prefixed with the given "prefix".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'World'.prefix('Hello')</td>
<td>'HelloWorld'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.replace(String, String) : String</h3>
<p>Replaces the first substring of the current String that matches the regular expression "regex" with the String "replacement".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello'.replace('(.*)ll', 'Wh')</td>
<td>'Who'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.replaceAll(String, String) : String</h3>
<p>Replaces each substring of the current String that matches the given regular expression "regex" with the String "replacement".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'TestTest'.replace('.st', 'erminated')</td>
<td>'TerminatedTerminated'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.size() : Integer</h3>
<p>Return the length of the current String.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.size()</td>
<td>10</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.startsWith(String) : Boolean</h3>
<p>Returns true if the current String starts with the string "b".</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'Hello'.startsWith('Hell')</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.strcmp(String) : Integer</h3>
<p>Returns an integer that is either negative, zero or positive depending on whether s1 is alphabetically less than, equal to or greater than self. Note that upper case letters come before lower case ones, so that 'AA' is closer to 'AC' than it is to 'Ab'.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'strcmp operation'.strcmp('strcmp')</td>
<td>10</td>
</tr>
<tr>
<td>'strcmp operation'.strcmp('strcmp operation')</td>
<td>0</td>
</tr>
<tr>
<td>'strcmp operation'.strcmp('strtok')</td>
<td>-17</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.strstr(String) : Boolean</h3>
<p>Searches r in self.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.strstr('World')</td>
<td>true</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.substitute(String, String) : String</h3>
<p>Substitutes the first occurrence of the substring "r" in self by "t" and returns the resulting string. Will return self if it contains no occurrence of the substring r.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'WorldWorld'.substitute('World', 'Hello')</td>
<td>'HelloWorld'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.substituteAll(String, String) : String</h3>
<p>Substitutes all occurences of the substring "r" in self by "t" and returns the resulting string. Will return self if it contains no occurrence of the substring r.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'WorldWorld'.substituteAll('World', 'Hello')</td>
<td>'HelloHello'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.substring(Integer, Integer) : String</h3>
<p>Returns a string containing all characters from self starting from index lower up to index upper included. Both lower and upper parameters should be contained between 1 and self.size() included. Lower cannot be greater than upper.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.substring(1, 5)</td>
<td>'Hello'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.substring(Integer) : String</h3>
<p>Returns a string containing all characters from self starting from index lower up to the end of the string included. The lower parameter should be contained between 1 and self.size() included. Lower cannot be greater than the size of the String.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.substring(5)</td>
<td>'World'</td>
</tr>
<tr>
<td>'HelloWorld'.substring(1)</td>
<td>'HelloWorld'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.toInteger() : Integer</h3>
<p>Returns an integer of value equal to self</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'42'.toInteger()</td>
<td>42</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.toLower() : String</h3>
<p>Returns the current String with all characters transformed to lower case.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.toLower()</td>
<td>'helloworld'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.toLowerFirst() : String</h3>
<p>Returns the self string with the first characters transformed to lower case.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.toLowerFirst()</td>
<td>'helloWorld'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.toReal() : Double</h3>
<p>Returns a real of value equal to self</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'41.9'.toReal()</td>
<td>41.9</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.toUpper() : String</h3>
<p>Returns the current String with all characters transformed to upper case.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'HelloWorld'.toUpper()</td>
<td>'HELLOWORLD'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.toUpperFirst() : String</h3>
<p>Returns the current String with the first characters transformed to upper case.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'helloworld'.toUpperFirst()</td>
<td>'Helloworld'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.tokenize(String) : Sequence{String}</h3>
<p>Splits the current String by using the given "delimiter" into a collection of String</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'a, b, c, d'.tokenize(', ')</td>
<td>['a', 'b', 'c', 'd']</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.tokenize() : Sequence{String}</h3>
<p>Splits the current String by whitespace delimiter into a collection of String</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>'a, b, c, d'.tokenize()</td>
<td>['a,', 'b,', 'c,', 'd']</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
<h3>String.trim() : String</h3>
<p>Trims the given String.</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>Expression</th>
<th>Result</th>
</tr>
</thead>
<colgroup>
<col width="60%" />
<col width="40%" />
</colgroup>
<tbody>
<tr>
<td>' Hello World '.trim()</td>
<td>'Hello World'</td>
</tr>
</tbody>
</table>
<p></p>
<hr />
</section>
<h3 id="SyntaxReference">Syntax Reference</h3>
<h4 id="References">References</h4>
<table>
<tr>
<td style="text-align: left;"><em>variable_name</em></td>
<td>a reference to a variable</td>
<td>myVariable</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>.</strong> <em>feature_name</em></td>
<td>implicit collect</td>
<td>eClass.name</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>.</strong> <em>service_name</em> <strong>(</strong> ( <em>expression</em> ( <strong>,</strong> <em>expression</em> ) * ) ? <strong>)</strong></td>
<td>implicit collect</td>
<td>myVariable.toString()</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>-&gt;</strong> <em>service_name</em> <strong>(</strong> ( <em>expression</em> ( <strong>,</strong> <em>expression</em> ) * ) ? <strong>)</strong></td>
<td>call on the collection itself if the expression is not a collection it will be wrapped into an ordered set</td>
<td>mySequence-&gt;sep(&#8249;,&#8250;)</td>
</tr>
</table>
<h4 id="Operators">Operators</h4>
<table>
<tr>
<td style="text-align: left;"><strong>not</strong> <em>expression</em></td>
<td>call the not service</td>
<td>not eClass.interface</td>
</tr>
<tr>
<td style="text-align: left;"><strong>-</strong> <em>expression</em></td>
<td>call the unaryMin service</td>
<td>-3</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>+</strong> <em>expression</em></td>
<td>call the add service</td>
<td>2 + 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>-</strong> <em>expression</em></td>
<td>call the sub service</td>
<td>2 &#8211; 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>&#42;</strong> <em>expression</em></td>
<td>call the mult service</td>
<td>2 * 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>&#47;</strong> <em>expression</em></td>
<td>call the divOp service</td>
<td>2 / 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>&lt;=</strong> <em>expression</em></td>
<td>call the lessThanEqual service</td>
<td>2 &lt;= 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>&gt;=</strong> <em>expression</em></td>
<td>call the greaterThanEqual service</td>
<td>2 &gt;= 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>&lt;</strong> <em>expression</em></td>
<td>call the lessThan service</td>
<td>1 &lt; 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>&gt;</strong> <em>expression</em></td>
<td>call the greaterThan service</td>
<td>2 &gt; 1</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>&lt;&gt;</strong> <em>expression</em></td>
<td>call the differs service</td>
<td>1 &lt;&gt; 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>!=</strong> <em>expression</em></td>
<td>call the differs service</td>
<td>1 != 2</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>=</strong> <em>expression</em></td>
<td>call the equals service</td>
<td>1 = 1</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>and</strong> <em>expression</em></td>
<td>call the and service</td>
<td>eClass.interface and eClass.abstact</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>or</strong> <em>expression</em></td>
<td>call the or service</td>
<td>eClass.interface or eClass.abstact</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>xor</strong> <em>expression</em></td>
<td>call the xor service</td>
<td>eClass.interface xor eClass.abstact</td>
</tr>
<tr>
<td style="text-align: left;"><em>expression</em> <strong>implies</strong> <em>expression</em></td>
<td>call implies service</td>
<td>eClass.interface implies eClass.abstact</td>
</tr>
</table>
<h4 id="Structures">Structures</h4>
<table>
<tr>
<td style="text-align: left;"><strong>(</strong> <em>expression</em> <strong>)</strong></td>
<td>parenthesis are used to change priority during evaluation</td>
<td>(2 + 2 ) * 3</td>
</tr>
<tr>
<td style="text-align: left;"><strong>if</strong> <em>expression</em> <strong>then</strong> <em>expression</em> <strong>else</strong> <em>expression</em> <strong>endif</strong></td>
<td>conditional expression</td>
<td>if eClass.abstract then &#8249;blue&#8250; else &#8249;red&#8250; endif</td>
</tr>
<tr>
<td style="text-align: left;"><strong>let</strong> <em>new_variable_name</em> ( <strong>:</strong> <em>type_literal</em>)? ( <strong>,</strong> <em>new_variable_name</em> ( <strong>:</strong> <em>type_literal</em>)?)* <strong>in</strong> <em>expression</em></td>
<td>let allows to define variables in order to factorise expression</td>
<td>let container = self.eContainer() in container.eAllContents()</td>
</tr>
</table>
<h4 id="Literals">Literals</h4>
<table>
<tr>
<td style="text-align: left;"><strong>'</strong> <em>escaped_string</em> <strong>'</strong></td>
<td>you can use java style escape sequence <strong>\u0000</strong> <strong>\x00</strong> <strong>\\</strong> <strong>\'</strong> <strong>\b</strong> <strong>\t</strong> <strong>\n</strong> ...
</td>
<td>'TODO list:\n\t- walk the dog\n\t- make diner'</td>
</tr>
<tr>
<td style="text-align: left;">[ <strong>0</strong> - <strong>9</strong>]+
</td>
<td>an integer</td>
<td>100</td>
</tr>
<tr>
<td style="text-align: left;">[ <strong>0</strong> - <strong>9</strong>]+ <strong>.</strong> [ <strong>0</strong> - <strong>9</strong>]+
</td>
<td>a real</td>
<td>3.14</td>
</tr>
<tr>
<td style="text-align: left;"><strong>true</strong></td>
<td>the boolean value true</td>
<td>true</td>
</tr>
<tr>
<td style="text-align: left;"><strong>false</strong></td>
<td>the boolean value false</td>
<td>false</td>
</tr>
<tr>
<td style="text-align: left;"><strong>null</strong></td>
<td>the null value</td>
<td>null</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Sequence{</strong> ( <em>expression</em> ( <strong>,</strong> <em>expression</em>) * ) ? <strong>}</strong></td>
<td>a sequence defined in extension</td>
<td>Sequence{1, 2, 3, 3}</td>
</tr>
<tr>
<td style="text-align: left;"><strong>OrderedSet{</strong> ( <em>expression</em> ( <strong>,</strong> <em>expression</em>) * ) ? <strong>}</strong></td>
<td>an ordered set defined in extension</td>
<td>OrderedSet{1, 2, 3}</td>
</tr>
<tr>
<td style="text-align: left;"><em>epackage_name</em> <strong>::</strong> <em>eenum_name</em> <strong>::</strong> <em>eenum_literal_name</em></td>
<td>an EEnumLiteral</td>
<td>art::Color::blue</td>
</tr>
</table>
<h4 id="Typeliterals">Type literals</h4>
<table>
<tr>
<td style="text-align: left;"><strong>String</strong></td>
<td>the string type</td>
<td>String</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Integer</strong></td>
<td>the integer type</td>
<td>Integer</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Real</strong></td>
<td>the real type</td>
<td>Real</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Boolean</strong></td>
<td>the string type</td>
<td>Boolean</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Sequence(</strong> <em>type_litral</em> <strong>)</strong></td>
<td>a sequence type</td>
<td>Sequence(String)</td>
</tr>
<tr>
<td style="text-align: left;"><strong>OrderedSet(</strong> <em>type_litral</em> <strong>)</strong></td>
<td>an ordered set type</td>
<td>OrderedSet(String)</td>
</tr>
<tr>
<td style="text-align: left;"><em>epackage_name</em> <strong>::</strong> <em>eclassifier_name</em></td>
<td>an eclassifier type</td>
<td>ecore::EPackage</td>
</tr>
<tr>
<td style="text-align: left;"><strong>{</strong> <em>epackage_name</em> <strong>::</strong> <em>eclassifier_name</em> (*</td>
<td>* <em>epackage_name</em> <strong>::</strong> <em>eclassifier_name</em>) * <strong>}</strong>
</td>
<td>a set of eclassifiers</td>
<td>{ecore::EPackage &#124; ecore::EClass}</td>
</tr>
</table>
<h2 id="MigratingfromMTLqueries">Migrating from MTL queries</h2>
<p>As languages, AQL and MTL are very close yet there are some notable differences:</p>
<h3 id="Implicitvariablereferences">Implicit variable references</h3>
<p>
There is no implicit variable reference. With this change, you can easily find out if you are using a feature of an object or a string representation of said object. As a result, instead of using
<code>something</code>
, you must use
<code>self.something</code>
if you want to access the feature named &#171;something&#187; of the current object or &#171;something&#187; if you want to retrieve the object named something.
</p>
<p>
In a lambda expression, you must now define the name of the variable used for the iteration in order to easily identify which variable is used by an expression. In Acceleo MTL, you can write
<code>Sequence{self}-&gt;collect(eAllContents(uml::Property))</code>
and Acceleo will use the implicit iterator as a source of the operation eAllContents.
</p>
<p>
The problem comes when using a lambda like
<code>Sequence{self}-&gt;collect(something)</code>
, we can&#8217;t know if &#171;something&#187; is a feature of &#171;self&#187; or if it is another variable.
</p>
<p>
Using AQL, you will now have to write either
<code>collect(m | m.eAllContents(uml::Property))</code>
or
<code>collect(m: uml::Model | eAllContents(uml::Property))</code>
.
</p>
<h3 id="Collectandflatten">Collect and flatten</h3>
<p>When a call or a feature acces is done on a collection the result is flattened for the first level. For instance a service returning a collection called on a collection will return a collection of elements and not a collection of collection of elements.</p>
<h3 id="TypeliteralschildrenEPackages">Type literals &amp; children EPackages</h3>
<p>
Type literals can&#8217;t be in the form someEPackage::someSubEPackage::SomeEClass but instead someSubEPackage::SomeEClass should be directly used. Note that the <b>name of the EPackage is mandatory</b>. Type literals are handled just like any other type.
</p>
<p>
Calls like
<code>self.eAllContents(self.eClass())</code>
are possible and will return all the children of type compatible with “self”.
</p>
<p>
Furthermore if you need a type literal as a parameter in your own service, you just have to have a first parameter with the type :
<code>Set&lt;EClass&gt;</code>
. Yes, that’s an important point, any type in AQL is possibly a union of several existing types, hence the collection here. As such the syntax for creating Sets or collections can be used as a substitute for type literals.
</p>
<h3 id="EnumerationliteralschildrenEPackages">Enumeration literals &amp; children EPackages</h3>
<p>Enumeration literal should be prefixed with the name of the containing EPacakge for instance &#171;myPackage::myEnum::value&#187;.</p>
<h3 id="Collections">Collections</h3>
<p>You can only have Sequences or OrderedSets as collections and as such the order of their elements is always deterministic. In Acceleo MTL, you had access to Sets, which are now OrderedSets and Bags, which are now Sequences. Those four kinds of collections were motivated by the fact that
Sequence and OrderedSet were ordered contrary to Sets and Bags. On another side, OrderedSets and Sets did not accept any duplicate contrary to Bags and Sequences.</p>
<p>By careful reviewing the use of those collections in various Acceleo generators and Sirius Designers we have quickly found out that the lack of determinism in the order of the collections Sets and Bags was a major issue for our users. As a result, only two collections remain, the Sequence
which can contain any kind of element and the OrderedSet which has a similar behavior except that it does not accept duplicates.</p>
<p>
Previously in Acceleo MTL, you could transform a literal into a collection by using the operator
<code>-&gt;</code>
on the literal directly. In Acceleo MTL, the collection created was a Bag which is not available anymore. It is recommended to use the extension notation like
<code>Sequence{self}</code>
or
<code>OrderedSet{self}</code>
. By default in AQL the created collection is an OrderedSet.
</p>
<h3 id="Renamedoperations">Renamed operations</h3>
<p>Some operations have been renamed. As such &#171;addAll&#187; and &#171;removeAll&#187; have been renamed &#171;add&#187; and &#171;sub&#187; because those two names are used by AQL in order to provide access to the operator &#171;+&#187; and &#171;-&#187;. As a result we can now write in
AQL &#171;firstSequence + secondSequence&#187; or &#171;firstSet - secondSet&#187;.</p>
<h3 id="Typing">Typing</h3>
<p>
AQL is way smarter than MTL regarding to the types of your expressions. As a result, you can combine expressions using multiple types quite easily. For example, this is a valid AQL expression
<code>self.eContents(uml::Class).add(self.eContents(ecore::EClass)).name</code>
. In Acceleo MTL, we could not use this behavior because Acceleo MTL had to fall back to the concept EObject which does not have a feature &#171;name&#187; while AQL knows that the collection contains objects that are either &#171;uml::Class&#187; or &#171;ecore::EClass&#187; and both of those
types have a feature named &#171;name&#187;.
</p>
<h3 id="nullhandling">null handling</h3>
<p>
AQL handles null (OclVoid) differently from ocl, a null value will not cause a failure but will be silently handled. <br />For example,
<code>null.oclIsKindOf(ecore::EClass)</code>
would have returned true for MTL/OCL, forcing users to use
<code>not self.oclIsUndefined() and self.oclIsKindOf(ecore::EClass)</code>
instead. This is no longer true in AQL, where &#171;null&#187; doesn&#8217;t conform to any type, so
<code>null.oclIsKindOf(ecore::EClass)</code>
will return false. Note that it&#8217;s still possible to &#171;cast&#187; null in any given classifier.
<code>null.oclAsType(ecore::EClass)</code>
will not fail at runtime.
</p>
<p>
Furthermore <strong>oclIsUndefined() does not exist in AQL</strong> and should be replaced by a
<code>... &lt;&gt; null</code>
expression.
</p>
<h2 id="MigratingfromAcceleo2queries">Migrating from Acceleo2 queries</h2>
<h3 id="EClassifierreferences">EClassifier references</h3>
<p>
All operations referencing a type are now using a type literal with the name of the EPackage and the name of the type instead of a string with the name of the type. As a result,
<code>eObject.eAllContents('EClass')</code>
would be translated using
<code>eObject.eAllContents('ecore::EClass')</code>
. This allows AQL to now in which EPackage to look for the type and as such, it improves the quality of the validation.
</p>
<h3 id="Typesandcast">Types and cast</h3>
<p>In order to test the type of an EObject, a common pattern in Acceleo 2 was to treat the EObject as a collection and filter said collection on the type desired to see if the size of the collection changed. In AQL, you have access to the operations oclIsTypeOf and oclIsKindOf. You can thus
test the type of an EObject with the expression &#171;eObject.oclIsKindOf(ecore::EStructuralFeature)&#187; or &#171;eObject.oclIsTypeOf(ecore::EAttribute)&#187;. You can use the operation oclIsKindOf to test if an object has the type of the given parameter or one of its subtype. On the other
hand, you can use the operation oclIsTypeOf to test if an object has exactly the type of the given parameter.</p>
<p>Casting in AQL is useless, since AQL is very understandable when it comes to types, it will always tries its best to evaluate your expression.</p>
<p>
Since AQL is very close to Acceleo MTL, you can find some additional documentation using the Acceleo equivalence documentation in the <a href="http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.acceleo.doc%2Fpages%2Freference%2Fmigration.html&amp;cp=5_3_4">Acceleo documentation</a>.
</p>
<h3 id="eContainerTypeName">eContainer(&#171;TypeName&#187;)</h3>
<p>
In Acceleo2
<code>self.eContainer("TypeName")</code>
actually had the behavior of returning self if it was matching the TypeName. As such, when migrating from an eContainer(..) call you should either make sure that this behavior is not needed or use the <br />compatibility method provided by AQL :
<code>self.eContainerOrSelf(some::Type)</code>
</p>
<h2 id="UsingAQLprogrammatically">Using AQL programmatically</h2>
<p>This section provide information and code snippet. It will help you to integrate AQL in your own tool.</p>
<p>Simple overview of AQL:</p>
<p>
<img border="0" src="../assets/pics/AQL_overview.png" />
</p>
<h3 id="Typevalidation">Type validation</h3>
<p>For each node of the AST we create a set of possible types as follow:</p>
<ul>
<li>for a VarRef we ask the environment for its possible types</li>
<li>for a FeatureAccess we look up the type of the feature in the registered metamodels</li>
<li>for a Call we look up the service in the service registry according to the possible types of its parameters (receiver is the first parameter). At this point there is a conversion from EMF to Java. The return type of the service is given by the IService.getType() method. At this point
there is a conversion form Java to EMF, one Java type can correspond to more than one EMF EClassifier. If no service can be found we try to find a corresponding EOperation if the receiver is an EObject.</li>
</ul>
<p>A special type NothingType is used to mark a problem on a given node of the AST. Those NothingTypes are then used to create validation messages. If an AST node has only NothingTypes validation messages will be set as errors for this node, otherwise they are set as warnings.</p>
<h3 id="Completion">Completion</h3>
<p>
The completion rely on the AST production and the type validation. <br />The identifier fragments preceding (prefix) and following (remaining) the cursor position are removed from the expression to parse. The prefix and remaining are used later to filter the proposals. Many filters can be
implemented: filter only on prefix, filter on prefix and remaining, same strategies with support for camel case, ...
</p>
<p>Completion on the AST:</p>
<ul>
<li>if there is no error node in the AST the completion provide any symbols that can follow an expression (&#171;+&#187;, &#171;-&#187;, ...).</li>
<li>if there is an ErrorExpression node in the AST the completion provides anything that can prefix an expression (&#171;not&#187;, &#171;-&#187;, variable name, type name, ...).</li>
<li>if there is an ErrorFeatureAccesOrCall node in the AST the completion provides feature and service names corresponding to the receiver possible types. It is also possible to add symbols that follow an expression if the prefix and remaining are already a valid feature or service name for
the receiver possible types.</li>
<li>if there is an ErrorCollectionCall node in the AST the completion provides collection service names. It is also possible to add symbols that follow an expression if the prefix and remaining are already a valid service name.</li>
<li>if there is an ErrorTypeLiteral node in the AST the completion provides EClassifier, EEnumLiteral names according to the state of the type description.</li>
</ul>
<h3 id="Creatingandsettingtheenvironment">Creating and setting the environment</h3>
<p>To get a fresh environment you can use one of the following snippet:</p>
<pre>
<code>IQueryEnvironment queryEnvironment = Query.newEnvironmentWithDefaultServices(null);
</code>
</pre>
<p>To get an environment with predefined services.</p>
<p>or</p>
<pre>
<code>IQueryEnvironment queryEnvironment = Query.newEnvironment(null);
</code>
</pre>
<p>To get an environment with no predefined services. It can be useful to create your own language primitives.</p>
<p>Note that you can also provide a CrossReferenceProvider to define the scope of cross references in your environment. See CrossReferencerToAQL for more details.</p>
<p>You can register new services Class as follow:</p>
<pre>
<code>ServiceRegistrationResult registrationResult = queryEnvironment.registerServicePackage(MyServices.class);
</code>
</pre>
<p>The registration result contains information about services overrides.</p>
<p>You can also register your EPackages. Only registered EPackages are used to validate and evaluate AQL expression.</p>
<pre>
<code>queryEnvironment.registerEPackage(MyEPackage.eINSTANCE);
</code>
</pre>
<p>In some cases you might also want to create custom mappings between an EClass and its Class. A basic case is the use of EMap:</p>
<pre>
<code>queryEnvironment.registerCustomClassMapping(EcorePackage.eINSTANCE.getEStringToStringMapEntry(), EStringToStringMapEntryImpl.class);
</code>
</pre>
<p>By default the EClass is mapped to Map.Entry which is not an EObject. This prevents using services on EObject.</p>
<h3 id="BuildinganAQLexpression">Building an AQL expression</h3>
<p>The first step is building your expression from a String to an AST:</p>
<pre>
<code>QueryBuilderEngine builder = new QueryBuilderEngine(queryEnvironment);
AstResult astResult = builder.build("self.name");
</code>
</pre>
<h3 id="EvaluatinganAQLexpression">Evaluating an AQL expression</h3>
<p>To evaluate an AQL expression you can use the QueryEvaluationEngine</p>
<pre>
<code>QueryEvaluationEngine engine = new QueryEvaluationEngine(queryEnvironment);
Map&lt;String, Object&gt; variables = Maps.newHashMap();
variables.put("self", EcorePackage.eINSTANCE);
EvaluationResult evaluationResult = engine.eval(astResult, variables);
</code>
</pre>
<p>Here we only use one variable for demonstration purpose.</p>
<h3 id="ValidatinganAQLexpressionoptional">Validating an AQL expression (optional)</h3>
<p>This step is optional for evaluation. You can evaluate an AQL expression without validating it in the first place.</p>
<pre>
<code>Map&lt;String, Set&lt;IType&gt;&gt; variableTypes = new LinkedHashMap&lt;String, Set&lt;IType&gt;&gt;();
Set&lt;IType&gt; selfTypes = new LinkedHashSet&lt;IType&gt;();
selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEPackage()));
variableTypes.put("self", selfTypes);
AstValidator validator = new AstValidator(queryEnvironment, variableTypes);
IValidationResult validationResult = validator.validate(astResult);
</code>
</pre>
<h3 id="CompletinganAQLexpression">Completing an AQL expression</h3>
<p>To do this use the QueryCompletionEngine, it will build the query and validate it for you. It will also compute needed prefix and suffix if any:</p>
<pre>
<code>Map&lt;String, Set&lt;IType&gt;&gt; variableTypes = new LinkedHashMap&lt;String, Set&lt;IType&gt;&gt;();
Set&lt;IType&gt; selfTypes = new LinkedHashSet&lt;IType&gt;();
selfTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEPackage()));
variableTypes.put("self", selfTypes);
QueryCompletionEngine engine = new QueryCompletionEngine(queryEnvironment);
ICompletionResult completionResult = engine.getCompletion("self.", 5, variableTypes);
List&lt;ICompletionProposal&gt; proposals = completionResult.getProposals(new BasicFilter(completionResult));
</code>
</pre>
<p>Here 5 is the offset where the completion should be computed in the given expression.</p>
</div>
</body>
</html>