[438557] Initial contribution

This is the exact code approved for contribution by CQ #8407.

Bug: 438557
Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2765fe4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+bin/
+target
+*~
+*.rej
+*.bak
+.DS_Store
+.directory
diff --git a/features/org.eclipse.sirius.query.legacy.feature/.project b/features/org.eclipse.sirius.query.legacy.feature/.project
new file mode 100644
index 0000000..0159e2a
--- /dev/null
+++ b/features/org.eclipse.sirius.query.legacy.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.sirius.query.legacy.feature</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+</projectDescription>
diff --git a/features/org.eclipse.sirius.query.legacy.feature/build.properties b/features/org.eclipse.sirius.query.legacy.feature/build.properties
new file mode 100644
index 0000000..ea1ebd2
--- /dev/null
+++ b/features/org.eclipse.sirius.query.legacy.feature/build.properties
@@ -0,0 +1,16 @@
+#===============================================================================
+# Copyright (c) 2005-2014 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:
+#    Obeo - initial API and implementation
+#===============================================================================
+bin.includes = feature.xml,\
+               epl-v10.html,\
+               feature.properties,\
+               license.html
+src.includes = feature.xml
diff --git a/features/org.eclipse.sirius.query.legacy.feature/epl-v10.html b/features/org.eclipse.sirius.query.legacy.feature/epl-v10.html
new file mode 100644
index 0000000..9c0feb7
--- /dev/null
+++ b/features/org.eclipse.sirius.query.legacy.feature/epl-v10.html
@@ -0,0 +1,259 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!-- saved from url=(0041)http://www.eclipse.org/legal/epl-v10.html -->
+<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+
+<title>Eclipse Public License - Version 1.0</title>
+<style type="text/css">
+  body {
+    size: 8.5in 11.0in;
+    margin: 0.25in 0.5in 0.25in 0.5in;
+    tab-interval: 0.5in;
+    }
+  p {  	
+    margin-left: auto;
+    margin-top:  0.5em;
+    margin-bottom: 0.5em;
+    }
+  p.list {
+  	margin-left: 0.5in;
+    margin-top:  0.05em;
+    margin-bottom: 0.05em;
+    }
+  </style>
+
+</head>
+
+<body lang="EN-US">
+
+<h2>Eclipse Public License - v 1.0</h2>
+
+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
+AGREEMENT.</p>
+
+<p><b>1. DEFINITIONS</b></p>
+
+<p>"Contribution" means:</p>
+
+<p class="list">a) in the case of the initial Contributor, the initial
+code and documentation distributed under this Agreement, and</p>
+<p class="list">b) in the case of each subsequent Contributor:</p>
+<p class="list">i) changes to the Program, and</p>
+<p class="list">ii) additions to the Program;</p>
+<p class="list">where such changes and/or additions to the Program
+originate from and are distributed by that particular Contributor. A
+Contribution 'originates' from a Contributor if it was added to the
+Program by such Contributor itself or anyone acting on such
+Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii)
+are not derivative works of the Program.</p>
+
+<p>"Contributor" means any person or entity that distributes
+the Program.</p>
+
+<p>"Licensed Patents" mean patent claims licensable by a
+Contributor which are necessarily infringed by the use or sale of its
+Contribution alone or when combined with the Program.</p>
+
+<p>"Program" means the Contributions distributed in accordance
+with this Agreement.</p>
+
+<p>"Recipient" means anyone who receives the Program under
+this Agreement, including all Contributors.</p>
+
+<p><b>2. GRANT OF RIGHTS</b></p>
+
+<p class="list">a) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free copyright license to reproduce, prepare derivative works
+of, publicly display, publicly perform, distribute and sublicense the
+Contribution of such Contributor, if any, and such derivative works, in
+source code and object code form.</p>
+
+<p class="list">b) Subject to the terms of this Agreement, each
+Contributor hereby grants Recipient a non-exclusive, worldwide,
+royalty-free patent license under Licensed Patents to make, use, sell,
+offer to sell, import and otherwise transfer the Contribution of such
+Contributor, if any, in source code and object code form. This patent
+license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor,
+such addition of the Contribution causes such combination to be covered
+by the Licensed Patents. The patent license shall not apply to any other
+combinations which include the Contribution. No hardware per se is
+licensed hereunder.</p>
+
+<p class="list">c) Recipient understands that although each Contributor
+grants the licenses to its Contributions set forth herein, no assurances
+are provided by any Contributor that the Program does not infringe the
+patent or other intellectual property rights of any other entity. Each
+Contributor disclaims any liability to Recipient for claims brought by
+any other entity based on infringement of intellectual property rights
+or otherwise. As a condition to exercising the rights and licenses
+granted hereunder, each Recipient hereby assumes sole responsibility to
+secure any other intellectual property rights needed, if any. For
+example, if a third party patent license is required to allow Recipient
+to distribute the Program, it is Recipient's responsibility to acquire
+that license before distributing the Program.</p>
+
+<p class="list">d) Each Contributor represents that to its knowledge it
+has sufficient copyright rights in its Contribution, if any, to grant
+the copyright license set forth in this Agreement.</p>
+
+<p><b>3. REQUIREMENTS</b></p>
+
+<p>A Contributor may choose to distribute the Program in object code
+form under its own license agreement, provided that:</p>
+
+<p class="list">a) it complies with the terms and conditions of this
+Agreement; and</p>
+
+<p class="list">b) its license agreement:</p>
+
+<p class="list">i) effectively disclaims on behalf of all Contributors
+all warranties and conditions, express and implied, including warranties
+or conditions of title and non-infringement, and implied warranties or
+conditions of merchantability and fitness for a particular purpose;</p>
+
+<p class="list">ii) effectively excludes on behalf of all Contributors
+all liability for damages, including direct, indirect, special,
+incidental and consequential damages, such as lost profits;</p>
+
+<p class="list">iii) states that any provisions which differ from this
+Agreement are offered by that Contributor alone and not by any other
+party; and</p>
+
+<p class="list">iv) states that source code for the Program is available
+from such Contributor, and informs licensees how to obtain it in a
+reasonable manner on or through a medium customarily used for software
+exchange.</p>
+
+<p>When the Program is made available in source code form:</p>
+
+<p class="list">a) it must be made available under this Agreement; and</p>
+
+<p class="list">b) a copy of this Agreement must be included with each
+copy of the Program.</p>
+
+<p>Contributors may not remove or alter any copyright notices contained
+within the Program.</p>
+
+<p>Each Contributor must identify itself as the originator of its
+Contribution, if any, in a manner that reasonably allows subsequent
+Recipients to identify the originator of the Contribution.</p>
+
+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
+
+<p>Commercial distributors of software may accept certain
+responsibilities with respect to end users, business partners and the
+like. While this license is intended to facilitate the commercial use of
+the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create
+potential liability for other Contributors. Therefore, if a Contributor
+includes the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and
+indemnify every other Contributor ("Indemnified Contributor")
+against any losses, damages and costs (collectively "Losses")
+arising from claims, lawsuits and other legal actions brought by a third
+party against the Indemnified Contributor to the extent caused by the
+acts or omissions of such Commercial Contributor in connection with its
+distribution of the Program in a commercial product offering. The
+obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In
+order to qualify, an Indemnified Contributor must: a) promptly notify
+the Commercial Contributor in writing of such claim, and b) allow the
+Commercial Contributor to control, and cooperate with the Commercial
+Contributor in, the defense and any related settlement negotiations. The
+Indemnified Contributor may participate in any such claim at its own
+expense.</p>
+
+<p>For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those
+performance claims and warranties, and if a court requires any other
+Contributor to pay any damages as a result, the Commercial Contributor
+must pay those damages.</p>
+
+<p><b>5. NO WARRANTY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
+ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to
+the risks and costs of program errors, compliance with applicable laws,
+damage to or loss of data, programs or equipment, and unavailability or
+interruption of operations.</p>
+
+<p><b>6. DISCLAIMER OF LIABILITY</b></p>
+
+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
+
+<p><b>7. GENERAL</b></p>
+
+<p>If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further action
+by the parties hereto, such provision shall be reformed to the minimum
+extent necessary to make such provision valid and enforceable.</p>
+
+<p>If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other
+software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the
+date such litigation is filed.</p>
+
+<p>All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of time
+after becoming aware of such noncompliance. If all Recipient's rights
+under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive.</p>
+
+<p>Everyone is permitted to copy and distribute copies of this
+Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The
+Agreement Steward reserves the right to publish new versions (including
+revisions) of this Agreement from time to time. No one other than the
+Agreement Steward has the right to modify this Agreement. The Eclipse
+Foundation is the initial Agreement Steward. The Eclipse Foundation may
+assign the responsibility to serve as the Agreement Steward to a
+suitable separate entity. Each new version of the Agreement will be
+given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version
+of the Agreement is published, Contributor may elect to distribute the
+Program (including its Contributions) under the new version. Except as
+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+rights or licenses to the intellectual property of any Contributor under
+this Agreement, whether expressly, by implication, estoppel or
+otherwise. All rights in the Program not expressly granted under this
+Agreement are reserved.</p>
+
+<p>This Agreement is governed by the laws of the State of New York and
+the intellectual property laws of the United States of America. No party
+to this Agreement will bring a legal action under this Agreement more
+than one year after the cause of action arose. Each party waives its
+rights to a jury trial in any resulting litigation.</p>
+
+
+
+</body></html>
\ No newline at end of file
diff --git a/features/org.eclipse.sirius.query.legacy.feature/feature.properties b/features/org.eclipse.sirius.query.legacy.feature/feature.properties
new file mode 100644
index 0000000..9604242
--- /dev/null
+++ b/features/org.eclipse.sirius.query.legacy.feature/feature.properties
@@ -0,0 +1,87 @@
+# ====================================================================
+# Copyright (c) 2005, 2014 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:
+#    Obeo - initial API and implementation
+# ====================================================================
+featureName = Acceleo 2 Evaluation Engine
+providerName = Eclipse.org
+copyright=\
+Copyright (c) 2005, 2014 Obeo.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n\
+\n\
+Contributors:\n\
+    Obeo - initial API and implementation\n
+licenseURL=license.html
+license=\
+Eclipse.org Software User Agreement\n\
+\n\
+Eclipse Foundation Software User Agreement\n\
+April 9, 2014\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS\n\
+(COLLECTIVELY "CONTENT").  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND\n\
+CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE\n\
+OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND\n\
+CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0\n\
+("EPL").  A copy of the EPL is provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse.org CVS repository ("Repository") in CVS\n\
+modules ("Modules") and made available as downloadable archives ("Downloads").\n\
+   \n\
+       - Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").\n\
+       - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(tm) ARchive) in a directory named "plugins".\n\
+       - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named "features".  Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins\n\
+         and/or Fragments associated with that Feature.\n\
+       - Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+ \n\
+The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and\n\
+Included Features should be contained in files named "license.html" ("Feature Licenses").  Abouts and Feature Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+       - The top-level (root) directory\n\
+       - Plug-in and Fragment directories\n\
+       - Inside Plug-ins and Fragments packaged as JARs\n\
+       - Sub-directories of the directory named "src" of certain Plug-ins\n\
+       - Feature directories\n\
+		\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the Eclipse Update Manager, you must agree to a license ("Feature Update License") during the\n\
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or\n\
+inform you where you can locate them.  Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in\n\
+that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE\n\
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+       - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+       - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+       - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+       - IBM Public License 1.0 (available at http://oss.software.ibm.com/developerworks/opensource/license10.html)	\n\
+       - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please\n\
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to\n\
+another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,\n\
+possession, or use, and re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.\n
diff --git a/features/org.eclipse.sirius.query.legacy.feature/feature.xml b/features/org.eclipse.sirius.query.legacy.feature/feature.xml
new file mode 100644
index 0000000..e373d7a
--- /dev/null
+++ b/features/org.eclipse.sirius.query.legacy.feature/feature.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2005-2014 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:
+     Obeo - initial API and implementation
+-->
+<feature
+      id="org.eclipse.sirius.query.legacy.feature"
+      label="%featureName"
+      version="2.10.0.qualifier"
+      provider-name="%providerName">
+
+   <copyright>
+      %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+      %license
+   </license>
+
+   <plugin
+         id="org.eclipse.sirius.query.legacy"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/features/org.eclipse.sirius.query.legacy.feature/license.html b/features/org.eclipse.sirius.query.legacy.feature/license.html
new file mode 100644
index 0000000..95ad95e
--- /dev/null
+++ b/features/org.eclipse.sirius.query.legacy.feature/license.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html -->
+<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>April 9, 2014</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+   (COLLECTIVELY "CONTENT").  USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+   CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW.  BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+   OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+   NOTICES INDICATED OR REFERENCED BELOW.  IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+   CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+   ("EPL").  A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+   For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+   repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p>
+
+<ul>
+       <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content.  Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li>
+       <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li>
+       <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.  Each Feature may be packaged as a sub-directory in a directory named "features".  Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins
+      and/or Fragments associated with that Feature.</li>
+       <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and
+Included Features should be contained in files named "license.html" ("Feature Licenses").  Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+       <li>The top-level (root) directory</li>
+       <li>Plug-in and Fragment directories</li>
+       <li>Inside Plug-ins and Fragments packaged as JARs</li>
+       <li>Sub-directories of the directory named "src" of certain Plug-ins</li>
+       <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the
+installation process.  If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them.  Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.  SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+       <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
+       <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+       <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+       <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+       <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT.  If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+   Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or
+   other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to
+   install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+   ("Specification").</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+   applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+   in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+   Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+       <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology
+       on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based
+       product.</li>
+       <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+       accessed and copied to the Target Machine.</li>
+       <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+       Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target
+       Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+       the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+       indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+   another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+   possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+
+
+</body></html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.sirius.query.legacy/.checkstyle b/plugins/org.eclipse.sirius.query.legacy/.checkstyle
new file mode 100644
index 0000000..53e941a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/.checkstyle
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <local-check-config name="Viewpoint" location="/Viewpoint/dev/code/CheckstyleConfiguration.xml" type="project" description="">
+    <additional-data name="protect-config-file" value="false"/>
+  </local-check-config>
+  <fileset name="all" enabled="true" check-config-name="Viewpoint" local="true">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
diff --git a/plugins/org.eclipse.sirius.query.legacy/.classpath b/plugins/org.eclipse.sirius.query.legacy/.classpath
new file mode 100644
index 0000000..96ab11f
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="doc"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.sirius.query.legacy/.project b/plugins/org.eclipse.sirius.query.legacy/.project
new file mode 100644
index 0000000..3d02365
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.sirius.query.legacy</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.core.resources.prefs b/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..e477db2
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//doc/Writing_Queries_Using_Legacy.html=utf-8
+encoding/<project>=US-ASCII
diff --git a/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.core.runtime.prefs b/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..29afaec
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Sun Mar 20 10:52:21 CET 2011
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8000cd6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/plugins/org.eclipse.sirius.query.legacy/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.query.legacy/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..cd093ed
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/META-INF/MANIFEST.MF
@@ -0,0 +1,42 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.sirius.query.legacy;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.sirius.query.legacy.AcceleoInterpreterPlugin
+Bundle-Vendor: %providerName
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.emf.edit,
+ com.google.guava;bundle-version="[11.0.2,16.0)",
+ org.eclipse.sirius.ecore.extender;bundle-version="[0.9.0,1.0.0)",
+ org.eclipse.sirius.common;bundle-version="[0.9.0,1.0.0)",
+ org.eclipse.help,
+ org.eclipse.emf.ecore,
+ org.eclipse.emf.ecore.xmi,
+ org.eclipse.jdt.core
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.sirius.query.legacy,
+ org.eclipse.sirius.query.legacy.business.internal.interpreter;x-friends:="org.eclipse.sirius.query.legacy.tests",
+ org.eclipse.sirius.query.legacy.ecore,
+ org.eclipse.sirius.query.legacy.ecore.factories,
+ org.eclipse.sirius.query.legacy.ecore.tools,
+ org.eclipse.sirius.query.legacy.gen,
+ org.eclipse.sirius.query.legacy.gen.template,
+ org.eclipse.sirius.query.legacy.gen.template.eval,
+ org.eclipse.sirius.query.legacy.gen.template.eval.log,
+ org.eclipse.sirius.query.legacy.gen.template.expressions,
+ org.eclipse.sirius.query.legacy.gen.template.scripts,
+ org.eclipse.sirius.query.legacy.gen.template.scripts.imports,
+ org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services,
+ org.eclipse.sirius.query.legacy.gen.template.statements,
+ org.eclipse.sirius.query.legacy.tools,
+ org.eclipse.sirius.query.legacy.tools.classloaders,
+ org.eclipse.sirius.query.legacy.tools.format,
+ org.eclipse.sirius.query.legacy.tools.log,
+ org.eclipse.sirius.query.legacy.tools.plugins,
+ org.eclipse.sirius.query.legacy.tools.resources,
+ org.eclipse.sirius.query.legacy.tools.strings
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.sirius.query.legacy/about.html b/plugins/org.eclipse.sirius.query.legacy/about.html
new file mode 100644
index 0000000..b180dcb
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/about.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!-- saved from url=(0043)http://www.eclipse.org/legal/epl/about.html -->
+<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+
+<title>About</title>
+<style type="text/css"></style></head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>June 5, 2006</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content").  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL").  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+
+</body></html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.sirius.query.legacy/build.properties b/plugins/org.eclipse.sirius.query.legacy/build.properties
new file mode 100644
index 0000000..2f1837d
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/build.properties
@@ -0,0 +1,20 @@
+# ====================================================================
+# Copyright (c) 2005-2014 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:
+#    Obeo - initial API and implementation
+# ====================================================================
+
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               plugin.properties,\
+               doc/,\
+               about.html
+javacWarnings.. = none
diff --git a/plugins/org.eclipse.sirius.query.legacy/doc/Writing_Queries_Using_Legacy.html b/plugins/org.eclipse.sirius.query.legacy/doc/Writing_Queries_Using_Legacy.html
new file mode 100644
index 0000000..5dc5182
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/doc/Writing_Queries_Using_Legacy.html
@@ -0,0 +1 @@
+<?xml version='1.0' encoding='utf-8' ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head><body><h1 id="WritingQueriesUsingtheLegacyRequestLanguage">Writing Queries Using the Legacy Request Language</h1><p>Before Sirius, the main query language used in Viewpoint was based on Acceleo 2, which is an older, incompatible version of Acceleo and is not maintained anymore. It is still currently deprecated and not maintained, but still supported through an optional extension to ease the transition for existing users who have VSMs using this language. We refer to it as the &#171;legacy language&#187; to avoid confusion with the newer Acceleo (version 3 and above). If you use it your Sirius project must declare a dependency to the <code>org.eclipse.sirius.query.legacy</code> plug-in to ensure the necessary support will be available wherever your modelers are used. You are also encouraged to update your VSMs to use one of the recommended languages supported by Sirius.</p><p>Expressions in this language are enclosed between <code>&lt;%</code> and <code>%&gt;</code> strings. For example, <code>&lt;%name%&gt;</code>. You can mix fixed strings and evaluated parts inside a single expression, for example <code>Some text &lt;%aComputedPart%&gt;. Some other &lt;%computedText%&gt;.</code> See the language&#8217;s <a href="http://www.acceleo.org/doc/obeo/fr/acceleo-2.6-reference.pdf">reference manual</a> for more details.</p><p>In the context of Sirius, you have access to a special feature which can be used to follow &#171;back-links&#187; or &#171;cross-references&#187;. From a given model element, this allows you to easily (and efficiently) find all the elements which refer to it in the scope of the models and representations in the same modeling project. This feature is available through the <code>~</code> operator, which has two forms:</p><ul><li><code>anExpression.~</code>: if <code>anExpression</code> evaluates to the model element <em>M</em>, then the expression will return the set of all model elements which have a direct reference to <em>M</em>.</li><li><code>anExpression.~ref</code>, where <code>ref</code> can be any valid name: if <code>anExpression</code> evaluates to the model element <em>M</em>, then the expression will return the set of all model elements which have a direct reference to <em>M</em> through a reference named <code>ref</code>.</li></ul><p>For example if model element <em>A</em> has a reference named <em>r1</em> to model element <em>C</em>, and <em>B</em> has a reference <em>r2</em> to <em>C</em>, then <code>C.~r1</code> will return <em>A</em> but not <em>B</em>, while <code>C.~</code> would return both <em>A</em> and <em>B</em>.</p><p><em>Warning:</em> To test a Java service invoked through a legacy language expression, you have to launch an Eclipse runtime or to type its parameters with <code>EObject</code> and then cast them to your domain types in the service body.The legacy language interpreter is not able to retrieve non-deployed service with domain types parameters.</p></body></html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.sirius.query.legacy/doc/Writing_Queries_Using_Legacy.textile b/plugins/org.eclipse.sirius.query.legacy/doc/Writing_Queries_Using_Legacy.textile
new file mode 100644
index 0000000..0a4a950
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/doc/Writing_Queries_Using_Legacy.textile
@@ -0,0 +1,13 @@
+h1. Writing Queries Using the Legacy Request Language
+
+Before Sirius, the main query language used in Viewpoint was based on Acceleo 2, which is an older, incompatible version of Acceleo and is not maintained anymore. It is still currently deprecated and not maintained, but still supported through an optional extension to ease the transition for existing users who have VSMs using this language. We refer to it as the "legacy language" to avoid confusion with the newer Acceleo (version 3 and above). If you use it your Sirius project must declare a dependency to the @org.eclipse.sirius.query.legacy@ plug-in to ensure the necessary support will be available wherever your modelers are used. You are also encouraged to update your VSMs to use one of the recommended languages supported by Sirius.
+
+Expressions in this language are enclosed between @<%@ and @%>@ strings. For example, @<%name%>@. You can mix fixed strings and evaluated parts inside a single expression, for example @Some text <%aComputedPart%>. Some other <%computedText%>.@ See the language's "reference manual":http://www.acceleo.org/doc/obeo/fr/acceleo-2.6-reference.pdf for more details.
+
+In the context of Sirius, you have access to a special feature which can be used to follow "back-links" or "cross-references". From a given model element, this allows you to easily (and efficiently) find all the elements which refer to it in the scope of the models and representations in the same modeling project. This feature is available through the @~@ operator, which has two forms:
+* @anExpression.~@: if @anExpression@ evaluates to the model element _M_, then the expression will return the set of all model elements which have a direct reference to _M_.
+* @anExpression.~ref@, where @ref@ can be any valid name: if @anExpression@ evaluates to the model element _M_, then the expression will return the set of all model elements which have a direct reference to _M_ through a reference named @ref@.
+
+For example if model element _A_ has a reference named _r1_ to model element _C_, and _B_ has a reference _r2_ to _C_, then @C.~r1@ will return _A_ but not _B_, while @C.~@ would return both _A_ and _B_.
+
+_Warning:_ To test a Java service invoked through a legacy language expression, you have to launch an Eclipse runtime or to type its parameters with @EObject@ and then cast them to your domain types in the service body.The legacy language interpreter is not able to retrieve non-deployed service with domain types parameters.
diff --git a/plugins/org.eclipse.sirius.query.legacy/doc/toc.xml b/plugins/org.eclipse.sirius.query.legacy/doc/toc.xml
new file mode 100644
index 0000000..fc9e8af
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/doc/toc.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!--
+  Copyright (c) 2007-2013 THALES GLOBAL SERVICES
+  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:
+       Obeo - Initial API and implementation
+-->
+<toc label="Sirius Support for Legacy Queries" link_to="../org.eclipse.sirius.doc/doc/toc.xml#moreSpecifierRefs" topic="doc/Writing_Queries_Using_Legacy.html">
+  <topic href="doc/Writing_Queries_Using_Legacy.html" label="Writing Queries Using the Legacy Request Language"/>
+</toc>
diff --git a/plugins/org.eclipse.sirius.query.legacy/plugin.properties b/plugins/org.eclipse.sirius.query.legacy/plugin.properties
new file mode 100644
index 0000000..20d0e7b
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/plugin.properties
@@ -0,0 +1,13 @@
+# ====================================================================
+# Copyright (c) 2005-2014 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:
+#    Obeo - initial API and implementation
+# ====================================================================
+
+pluginName = Sirius Support for Acceleo 2 Expressions
+providerName = Eclipse.org
diff --git a/plugins/org.eclipse.sirius.query.legacy/plugin.xml b/plugins/org.eclipse.sirius.query.legacy/plugin.xml
new file mode 100644
index 0000000..d3049f5
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/plugin.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+
+<!--
+  Copyright (c) 2005-2014 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:
+       Obeo - Initial API and implementation
+-->
+
+<plugin>
+   <extension
+         id="org.eclipse.sirius.query.legacy.interpreter.AcceleoExtendedInterpreter"
+         point="org.eclipse.sirius.common.expressionInterpreter">
+      <expressionInterpreterProvider
+            interpreterProviderClass="org.eclipse.sirius.query.legacy.business.internal.interpreter.AcceleoExtendedInterpreter">
+      </expressionInterpreterProvider>
+   </extension>
+   <extension
+         point="org.eclipse.sirius.common.proposalProvider">
+      <proposalProvider
+            class="org.eclipse.sirius.query.legacy.business.internal.interpreter.AcceleoExtendedInterpreter"
+            interpreter="org.eclipse.sirius.query.legacy.interpreter.AcceleoExtendedInterpreter">
+      </proposalProvider>
+   </extension>
+      <extension point="org.eclipse.help.toc">
+      <toc file="doc/toc.xml" primary="false" />
+   </extension>
+
+</plugin>
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/AcceleoInterpreterPlugin.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/AcceleoInterpreterPlugin.java
new file mode 100644
index 0000000..3b3c18e
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/AcceleoInterpreterPlugin.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy;
+
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.sirius.query.legacy.business.internal.interpreter.IAcceleoInterpreterMessages;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalFailure;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalLog;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle.
+ * 
+ * @author ymortier
+ */
+public class AcceleoInterpreterPlugin extends Plugin {
+
+    /** The plug-in ID . */
+    public static final String PLUGIN_ID = "org.eclipse.sirius.query.legacy";
+
+    // The shared instance
+    private static AcceleoInterpreterPlugin plugin;
+
+    /**
+     * The constructor.
+     */
+    public AcceleoInterpreterPlugin() {
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
+     */
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        super.start(context);
+        plugin = this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+     */
+    @Override
+    public void stop(final BundleContext context) throws Exception {
+        plugin = null;
+        super.stop(context);
+    }
+
+    /**
+     * Returns the shared instance.
+     * 
+     * @return the shared instance
+     */
+    public static AcceleoInterpreterPlugin getDefault() {
+        return plugin;
+    }
+
+    /**
+     * Logs the given message and throwable as an error.
+     * 
+     * @param message
+     *            the message.
+     * @param t
+     *            the exception.
+     */
+    public void error(final String message, final Throwable t) {
+        final IStatus status = new Status(IStatus.ERROR, PLUGIN_ID, message, t);
+        this.getLog().log(status);
+    }
+
+    /**
+     * Logs the given message and throwable as a warning.
+     * 
+     * @param message
+     *            the message.
+     * @param t
+     *            the exception.
+     */
+    public void warning(final String message, final Throwable t) {
+        final IStatus status = new Status(IStatus.WARNING, PLUGIN_ID, message, t);
+        this.getLog().log(status);
+    }
+
+    /**
+     * Logs the given message as an information.
+     * 
+     * @param message
+     *            the message.
+     */
+    public void info(final String message) {
+        final IStatus status = new Status(IStatus.INFO, PLUGIN_ID, message);
+        this.getLog().log(status);
+    }
+
+    /**
+     * Log the error of the node.
+     * 
+     * @param node
+     *            the node.
+     * @param subStatus
+     *            the subStatus
+     */
+    public void logENode(final ENode node, final IStatus subStatus) {
+        final EvalLog evalLog = node.log();
+        final MultiStatus bigStatus = new MultiStatus(this.getBundle().getSymbolicName(), IStatus.ERROR, IAcceleoInterpreterMessages.EVALUATION_ERROR, new RuntimeException(evalLog.toString()));
+        if (!evalLog.isOk()) {
+            @SuppressWarnings("unchecked")
+            final Iterator<EvalFailure> iterErrors = evalLog.allOrderedErrorsAndSevereWarnings();
+            while (iterErrors.hasNext()) {
+                final EvalFailure failure = iterErrors.next();
+                final IStatus status = new Status(IStatus.INFO, this.getBundle().getSymbolicName(), failure.getMessage());
+                bigStatus.add(status);
+            }
+            if (subStatus != null) {
+                if (subStatus.isMultiStatus()) {
+                    bigStatus.addAll(subStatus);
+                } else {
+                    bigStatus.add(subStatus);
+                }
+            }
+        }
+        this.getLog().log(bigStatus);
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoCompletionEntry.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoCompletionEntry.java
new file mode 100644
index 0000000..13e9e61
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoCompletionEntry.java
@@ -0,0 +1,795 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EAnnotation;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EOperation;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.ETypeParameter;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentContext;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentInstanceContext;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentProposal;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalJavaService;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.ContextServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.ENodeServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.EObjectServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.PropertiesServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.RequestServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.ResourceServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.StringServices;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * This utility class evaluates the proposals of the Content Assist.
+ * 
+ * @author ggebhart
+ * 
+ */
+public class AcceleoCompletionEntry {
+
+    /**
+     * proposal contents key of the tools map.
+     * 
+     */
+    public static final Integer PROPOSAL = Integer.valueOf(0);
+
+    /**
+     * display contents key of the tools map.
+     * 
+     */
+    public static final Integer DISPLAY = Integer.valueOf(1);
+
+    /**
+     * information contents key of the tools map.
+     * 
+     */
+    public static final Integer INFORMATION = Integer.valueOf(2);
+
+    /**
+     * The activation characters for completion proposal.
+     */
+    protected static final char[] ACTIVATION_CHARACTERS = new char[] { ' ', '\t', '\n', '|', '&', '=', '(', ',', '-', '+', '*', '/', '!', '{', '[' };
+
+    /**
+     * The parenthesis characters.
+     */
+    protected static final char[] PARENTHESIS = new char[] { '(', ')' };
+
+    /**
+     * The brackets characters.
+     */
+    protected static final char[] BRACKETS = new char[] { '[', ']' };
+
+    /**
+     * The comma and space characters.
+     */
+    protected static final String COMMA = ", ";
+
+    /**
+     * The current context element.
+     */
+    protected EObject element;
+
+    /**
+     * Semantic element of the mapping or tools description.
+     */
+    private String metaClass = "";
+
+    private String qualifier = "";
+
+    private EPackage.Registry runtimeTypeRegistry = EPackage.Registry.INSTANCE;
+
+    /**
+     * Constructor.
+     * 
+     */
+    public AcceleoCompletionEntry() {
+
+    }
+
+    /**
+     * Evaluates the content proposals for a given expression and returns the
+     * result as an List.
+     * 
+     * @param context
+     *            the context.
+     * @return the content proposals list.
+     */
+    public List<ContentProposal> computeProposals(final ContentContext context) {
+
+        final Collection<String> targetTypes = context.getInterpreterContext().getTargetTypes();
+        if (!context.getInterpreterContext().requiresTargetType()) {
+            metaClass = "ecore.EObject";
+        } else if (targetTypes.size() == 1) {
+            metaClass = targetTypes.iterator().next();
+        }
+        element = context.getInterpreterContext().getElement();
+        final EClassifier[] proposals = computeMetamodelTypesProposals(getElementClassifierList(context.getInterpreterContext().getElement(), context.getContents()), context.getContents(), false);
+        final List<ContentProposal> contentsMap = computeResolvedTypesProposals(proposals, context.getContents(), context.getPosition());
+
+        // Delete duplicated proposals
+        return deleteDuplicatedProposals(contentsMap);
+    }
+
+    /**
+     * Evaluates the content proposals for a given expression and returns the
+     * result as an List.
+     * 
+     * @param context
+     *            the context.
+     * @return the content proposals list.
+     */
+    public List<ContentProposal> computeProposals(final ContentInstanceContext context) {
+
+        final EClassifier[] proposals = computeMetamodelTypesProposals(getElementClassifierList(context.getCurrentSelected(), context.getTextSoFar()), context.getTextSoFar(), false);
+        final List<ContentProposal> contentsMap = computeResolvedTypesProposals(proposals, context.getTextSoFar(), context.getCursorPosition());
+
+        // Delete duplicated proposals
+        return deleteDuplicatedProposals(contentsMap);
+    }
+
+    /**
+     * Returns the available ePackages according to the given EObject.
+     * 
+     * @param eObject
+     *            the currently selected {@link EObject}
+     * @param textSoFar
+     *            the typed expression
+     * 
+     * @return the available ePackages according to the given {@link EClass}
+     */
+    private List<EClassifier> getElementClassifierList(EObject eObject, String textSoFar) {
+        List<EClassifier> eClassifiers = new ArrayList<EClassifier>();
+        // If selection is not null and if expression is focusing on currently
+        // selected element, getting all EClassifiers extended by this
+        // element
+        if (eObject != null && textSoFar.replace(" ", "").equals("<%%>") || textSoFar.replace(" ", "").equals("<%self%>")) {
+            eClassifiers.addAll(getElementClassifierList(eObject.eClass()));
+        } else {
+            // Otherwise, get package registry
+
+            final Collection<Object> values = new ArrayList<Object>(runtimeTypeRegistry.values());
+            for (final Object value : values) {
+                try {
+                    if (value instanceof EPackage) {
+                        eClassifiers.addAll(((EPackage) value).getEClassifiers());
+                    } else if (value instanceof EPackage.Descriptor) {
+                        eClassifiers.addAll((((EPackage.Descriptor) value).getEPackage()).getEClassifiers());
+                    }
+                    // CHECKSTYLE:OFF
+                } catch (Throwable e) {
+                    /*
+                     * anything might happen here depending on the other Eclipse
+                     * tools, and we've seen many time tools (like XText for
+                     * instance) breaking all the others .
+                     */
+                    // CHECKSTYLE:ON
+                }
+            }
+        }
+        return eClassifiers;
+    }
+
+    /**
+     * Returns the available {@link EClassifier}s according to the given
+     * {@link EClass}.
+     * 
+     * @param eClass
+     *            the currently selected {@link EObject}'s {@link EClass}
+     * 
+     * @return the available {@link EClassifier}s according to the given
+     *         {@link EClass}
+     */
+    private Set<EClass> getElementClassifierList(EClass eClass) {
+
+        final Set<EClass> eClassifiers = new LinkedHashSet<EClass>();
+        // Adding the current EObject's EClass's package
+        eClassifiers.add(eClass);
+        // Also adding the EPackages holding the super classes of the current
+        // EObject
+        for (EClass superClass : eClass.getESuperTypes()) {
+            if (!eClassifiers.contains(superClass)) {
+                eClassifiers.addAll(getElementClassifierList(superClass));
+            }
+        }
+        return eClassifiers;
+    }
+
+    /**
+     * Removes the duplicated proposals.
+     * 
+     * @param matches
+     *            are the initial proposals
+     * @return the valid proposals
+     */
+    private List<ContentProposal> deleteDuplicatedProposals(final List<ContentProposal> contents) {
+
+        final List<ContentProposal> resultProposals = new ArrayList<ContentProposal>(contents.size());
+        final Iterator<ContentProposal> it = contents.iterator();
+        while (it.hasNext()) {
+            final ContentProposal entry = it.next();
+            if (!resultProposals.contains(entry)) {
+                resultProposals.add(entry);
+            }
+        }
+        Collections.sort(resultProposals);
+        return resultProposals;
+    }
+
+    /**
+     * Computes valid metamodel types proposals.
+     * 
+     * @param classes
+     *            the available {@link EClass}es
+     * @param start
+     *            is the start of the proposal
+     * @param offset
+     *            is the offset within the text for which completions should be
+     *            computed
+     * @param classOnly
+     *            indicates that only the classes are kept
+     * @return the proposals
+     */
+    private EClassifier[] computeMetamodelTypesProposals(final List<EClassifier> classes, final String start, final boolean classOnly) {
+
+        final Collection<EClassifier> classifiers = new TreeSet<EClassifier>(new Comparator<EClassifier>() {
+            public int compare(final EClassifier c0, final EClassifier c1) {
+                return ETools.getEClassifierShortPath(c0).compareTo(ETools.getEClassifierShortPath(c1));
+            }
+        });
+        Iterables.addAll(classifiers, classes);
+
+        /* remove classifier with null name */
+        final Iterator<EClassifier> it = classifiers.iterator();
+        while (it.hasNext()) {
+            final EClassifier eClassifier = it.next();
+            if (eClassifier.getName() == null) {
+                it.remove();
+            }
+        }
+
+        /*
+         * Add EObject as a default type
+         */
+        classifiers.add(EcorePackage.eINSTANCE.getEObject());
+
+        final EClassifier[] proposals = classifiers.toArray(new EClassifier[classifiers.size()]);
+        final String[] replacementStrings = new String[proposals.length * 2];
+        final String[] displayStrings = new String[proposals.length * 2];
+        final String[] informationStrings = new String[proposals.length * 2];
+        final int[] cursorPositions = new int[proposals.length * 2];
+
+        for (int i = 0; i < proposals.length; i++) {
+            // Name only
+            final EClassifier currentProposal = proposals[i];
+            replacementStrings[i] = currentProposal.getName();
+            cursorPositions[i] = replacementStrings[i].length();
+            displayStrings[i] = currentProposal.getName();
+            informationStrings[i] = AcceleoCompletionEntry.getDescription(currentProposal);
+
+            // Short path
+            final int j = proposals.length + i;
+            replacementStrings[j] = ETools.getEClassifierShortPath(currentProposal);
+            cursorPositions[j] = replacementStrings[j].length();
+            displayStrings[j] = replacementStrings[j];
+            informationStrings[j] = informationStrings[i];
+
+        }
+        return proposals;
+    }
+
+    /**
+     * Computes valid proposals for the objects detected.
+     * 
+     * @param proposals
+     *            are the objects detected for the current resolved type
+     * @param text
+     *            is the text
+     * @param offset
+     *            is the offset within the text for which completions should be
+     *            computed
+     * @return the proposals
+     */
+    private List<ContentProposal> computeResolvedTypesProposals(final Object[] proposal, final String text, final int offset) {
+        final String endStart = AcceleoCompletionEntry.extractEndStart(text, offset);
+        final Object[] proposals = getAllContents(proposal);
+
+        final String[] replacementStrings = new String[proposals.length];
+        final String[] displayStrings = new String[proposals.length];
+        final String[] informationStrings = new String[proposals.length];
+        final int[] cursorPositions = new int[proposals.length];
+
+        for (int i = 0; i < replacementStrings.length; i++) {
+            replacementStrings[i] = null;
+            if (proposals[i] instanceof Method) {
+
+                AcceleoCompletionEntry.computeForMethod(proposals, replacementStrings, displayStrings, informationStrings, cursorPositions, i);
+
+            } else if (proposals[i] instanceof EOperation) {
+
+                AcceleoCompletionEntry.computeForEOperation(proposals, replacementStrings, displayStrings, informationStrings, cursorPositions, i);
+
+            } else if (proposals[i] instanceof EAttribute) {
+
+                AcceleoCompletionEntry.computeForEAttribute(proposals, replacementStrings, displayStrings, informationStrings, cursorPositions, i);
+
+            } else if (proposals[i] instanceof EReference) {
+
+                AcceleoCompletionEntry.computeForEReference(proposals, replacementStrings, displayStrings, informationStrings, cursorPositions, i);
+
+            } else {
+                replacementStrings[i] = proposals[i].toString();
+                displayStrings[i] = proposals[i].toString();
+                informationStrings[i] = proposals[i].toString();
+                cursorPositions[i] = replacementStrings[i].length();
+
+            }
+            if (endStart.startsWith(TemplateConstants.FEATURE_BEGIN) && replacementStrings[i] != null) {
+                // For '<%link' proposals
+                replacementStrings[i] = TemplateConstants.FEATURE_BEGIN + replacementStrings[i];
+                cursorPositions[i] = cursorPositions[i] + TemplateConstants.FEATURE_BEGIN.length();
+            }
+        }
+        return computeValidProposals(proposals, replacementStrings, displayStrings, informationStrings, cursorPositions, endStart, offset);
+    }
+
+    private static void computeForMethod(final Object[] proposals, final String[] replacementStrings, final String[] displayStrings, final String[] informationStrings, final int[] cursorPositions,
+            final int i) {
+        final Method method = (Method) proposals[i];
+        StringBuilder replacementString = new StringBuilder(method.getName());
+        replacementString.append('(');
+        cursorPositions[i] = replacementString.length();
+        StringBuilder displayString = new StringBuilder(method.getName());
+        displayString.append(" ("); //$NON-NLS-1$
+        final Class<?>[] paramTypes = method.getParameterTypes();
+        for (int j = 1; j < paramTypes.length; j++) { // The first
+            // parameter is
+            // ignored
+            final Class<?> paramType = paramTypes[j];
+            replacementString.append(EvalJavaService.getSimpleName(paramType)); // add
+            // args
+            // to
+            // proposals
+            // definition
+            displayString.append(EvalJavaService.getSimpleName(paramType));
+            if (j + 1 < paramTypes.length) {
+                replacementString.append(AcceleoCompletionEntry.COMMA);
+                displayString.append(AcceleoCompletionEntry.COMMA);
+            }
+        }
+        replacementString.append(')');
+        displayString.append(')');
+        if (method.getReturnType() != null) {
+            displayString.append(' ');
+            displayString.append(EvalJavaService.getSimpleName(method.getReturnType()));
+        }
+        displayString.append(" - ");
+        displayString.append(EvalJavaService.getSimpleName(method.getDeclaringClass())); //$NON-NLS-1$
+        replacementStrings[i] = replacementString.toString();
+        displayStrings[i] = displayString.toString();
+        informationStrings[i] = method.toString();
+    }
+
+    private static void computeForEAttribute(final Object[] proposals, final String[] replacementStrings, final String[] displayStrings, final String[] informationStrings,
+            final int[] cursorPositions, final int i) {
+        final EAttribute attribute = (EAttribute) proposals[i];
+        replacementStrings[i] = attribute.getName();
+        if (replacementStrings[i] != null) {
+            cursorPositions[i] = replacementStrings[i].length();
+        } else {
+            cursorPositions[i] = 0;
+        }
+        String displayString = attribute.getName();
+        if (attribute.getEType() != null) {
+            displayString += " : " + attribute.getEType().getName(); //$NON-NLS-1$
+        }
+        displayStrings[i] = displayString;
+        informationStrings[i] = displayString;
+    }
+
+    private static void computeForEReference(final Object[] proposals, final String[] replacementStrings, final String[] displayStrings, final String[] informationStrings,
+            final int[] cursorPositions, final int i) {
+        final EReference reference = (EReference) proposals[i];
+
+        replacementStrings[i] = reference.getName();
+        if (replacementStrings[i] != null) {
+            cursorPositions[i] = replacementStrings[i].length();
+        } else {
+            cursorPositions[i] = 0;
+        }
+        String displayString = reference.getName();
+        if (reference.getEType() != null) {
+
+            final int lowerBound = reference.getLowerBound();
+            final int upperBound = reference.getUpperBound();
+            String bounds;
+            if (lowerBound == upperBound) {
+                bounds = String.valueOf(lowerBound);
+            } else {
+                bounds = lowerBound + (upperBound != -1 ? ".." + upperBound : "..*"); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+            if (reference.isContainment()) {
+                bounds = '[' + bounds + ']';
+            } else {
+                bounds = '{' + bounds + '}';
+            }
+            displayString += " : " + reference.getEType().getName() + ' ' + bounds;
+
+            displayStrings[i] = displayString;
+            informationStrings[i] = displayString;
+        }
+    }
+
+    private static void computeForEOperation(final Object[] proposals, final String[] replacementStrings, final String[] displayStrings, final String[] informationStrings,
+            final int[] cursorPositions, final int i) {
+        final EOperation method = (EOperation) proposals[i];
+        StringBuilder replacementString;
+
+        replacementString = new StringBuilder(method.getName());
+        replacementString.append('(');
+        cursorPositions[i] = replacementString.length();
+        StringBuilder displayString = new StringBuilder(method.getName());
+        displayString.append(" ("); //$NON-NLS-1$
+        final EList<ETypeParameter> paramTypes = method.getETypeParameters();
+
+        for (int j = 1; j < paramTypes.size(); j++) { // The first
+            // parameter is
+            // ignored
+            final ETypeParameter paramType = paramTypes.get(j);
+            displayString.append(paramType.getName());
+            if (j + 1 < paramTypes.size()) {
+                replacementString.append(AcceleoCompletionEntry.COMMA);
+                displayString.append(AcceleoCompletionEntry.COMMA);
+            }
+        }
+
+        replacementString.append(')');
+        displayString.append(')');
+        replacementStrings[i] = replacementString.toString();
+        displayStrings[i] = displayString.toString();
+        informationStrings[i] = method.toString();
+    }
+
+    /**
+     * Computes valid proposals (CompletionProposal).
+     * 
+     * @param objects
+     *            are the optional objects
+     * @param replacementStrings
+     *            are the replacement strings
+     * @param displayStrings
+     *            are the display strings
+     * @param informationStrings
+     *            are the information strings
+     * @param cursorPositions
+     *            are the cursor positions after the replacement
+     * @param start
+     *            is the start of the proposal
+     * @param offset
+     *            is the offset within the text for which completions should be
+     *            computed
+     * @param images
+     *            are the icons
+     * @return the proposals (CompletionProposal)
+     */
+    private List<ContentProposal> computeValidProposals(final Object[] objects, final String[] replacementStrings, final String[] displayStrings, final String[] informationStrings,
+            final int[] cursorPositions, final String start, final int offset) {
+        final ArrayList<ContentProposal> proposals = new ArrayList<ContentProposal>();
+        final String startToLowerCase = start.toLowerCase();
+
+        for (int i = 0; i < replacementStrings.length; i++) {
+            final String replacementString = replacementStrings[i];
+            if (replacementString != null) {
+                final String displayString = displayStrings[i];
+                final String informationString = informationStrings[i];
+                final String replacementStringL = replacementString.toLowerCase();
+                if (start.length() == 0
+                        || replacementStringL.startsWith(startToLowerCase)
+                        || replacementStringL.indexOf(TemplateConstants.LINK_PREFIX_SEPARATOR
+                                + (startToLowerCase.startsWith(TemplateConstants.FEATURE_BEGIN) ? startToLowerCase.substring(TemplateConstants.FEATURE_BEGIN.length()) : startToLowerCase)) > -1) {
+
+                    proposals.add(new ContentProposal(replacementString.replaceFirst(TemplateConstants.FEATURE_BEGIN, ""), displayString, informationString));
+                }
+            }
+        }
+
+        proposals.trimToSize();
+
+        return proposals;
+    }
+
+    /**
+     * Computes proposals for the objects detected.
+     * 
+     * @param proposals
+     *            are the objects detected for the current resolved type
+     * @return the proposals
+     */
+    private Object[] getAllContents(final Object[] proposals) {
+        Object[] newProposals = null;
+        Method[] allMethodsTab = null;
+        List<Object> contents = Lists.newArrayList();
+
+        addModelElements(proposals, contents);
+
+        /* add all acceleo and EMF services */
+        allMethodsTab = EObjectServices.class.getDeclaredMethods();
+        newProposals = getPublicMethod(allMethodsTab);
+        for (Object newProposal : newProposals) {
+            contents.add(newProposal);
+        }
+
+        allMethodsTab = ContextServices.class.getDeclaredMethods();
+        newProposals = getPublicMethod(allMethodsTab);
+        for (Object newProposal : newProposals) {
+            contents.add(newProposal);
+        }
+
+        allMethodsTab = ENodeServices.class.getDeclaredMethods();
+        newProposals = getPublicMethod(allMethodsTab);
+        for (Object newProposal : newProposals) {
+            contents.add(newProposal);
+        }
+
+        allMethodsTab = PropertiesServices.class.getDeclaredMethods();
+        newProposals = getPublicMethod(allMethodsTab);
+        for (Object newProposal : newProposals) {
+            contents.add(newProposal);
+        }
+
+        allMethodsTab = RequestServices.class.getDeclaredMethods();
+        newProposals = getPublicMethod(allMethodsTab);
+        for (Object newProposal : newProposals) {
+            contents.add(newProposal);
+        }
+
+        allMethodsTab = StringServices.class.getDeclaredMethods();
+        newProposals = getPublicMethod(allMethodsTab);
+        for (Object newProposal : newProposals) {
+            contents.add(newProposal);
+
+        }
+
+        allMethodsTab = ResourceServices.class.getDeclaredMethods();
+        newProposals = getPublicMethod(allMethodsTab);
+        for (Object newProposal : newProposals) {
+            contents.add(newProposal);
+        }
+        newProposals = contents.toArray();
+        return newProposals;
+    }
+
+    /**
+     * Add model elements (structural features) to completion.
+     * 
+     * @param proposals
+     *            the initial proposals
+     * @param contents
+     *            the modified proposals
+     */
+    protected void addModelElements(final Object[] proposals, List<Object> contents) {
+        EClassifier classifier = null;
+        EClass current = null;
+        for (Object proposal2 : proposals) {
+            classifier = (EClassifier) proposal2;
+            if (classifier instanceof EClass) {
+                current = (EClass) classifier;
+                if (metaClass != null && classifier.getName().equals(metaClass) && (qualifier == null || current.getEPackage().getNsURI().contains(qualifier))) {
+                    contents.clear();
+                    contents.addAll(current.getEAllAttributes());
+                    contents.addAll(current.getEAllReferences());
+                    break;
+
+                } else {
+                    contents.addAll(current.getEAllAttributes());
+                    contents.addAll(current.getEAllReferences());
+                }
+            }
+        }
+    }
+
+    /**
+     * Computes public methods
+     * 
+     * 
+     * @param tab
+     *            array of API's methods
+     * @return array of public method contained in a API
+     */
+    private Method[] getPublicMethod(final Method[] tab) {
+        final ArrayList<Method> publicMethods = new ArrayList<Method>();
+
+        for (Method element2 : tab) {
+            if (element2.getModifiers() == Modifier.PUBLIC) {
+                publicMethods.add(element2);
+            }
+        }
+        publicMethods.trimToSize();
+
+        final Method[] methods = new Method[publicMethods.size()];
+        for (int i = 0; i < methods.length; i++) {
+            methods[i] = publicMethods.get(i);
+        }
+        return methods;
+    }
+
+    /**
+     * Gets the completion's start, after the last dot.
+     * <p>
+     * Sample : "a.b.c.DDD" -> "DDD"
+     * 
+     * @param text
+     *            is the text
+     * @param offset
+     *            is the offset within the text for which completions should be
+     *            computed
+     * @return the completion's start, after the last dot
+     */
+    private static String extractEndStart(final String text, final int offset) {
+        final String extractStart = AcceleoCompletionEntry.extractStart(text, offset);
+        final Int2 iSep = TextSearch.getDefaultSearch().lastIndexOf(extractStart, TemplateConstants.CALL_SEP, TemplateConstants.SPEC, TemplateConstants.INHIBS_EXPRESSION);
+        final Int2 iBracket = AcceleoCompletionEntry.getLastIndexOfOpenBracket(extractStart, iSep.e() == -1 ? 0 : iSep.e());
+
+        String endStart;
+
+        if (iBracket.e() > -1) {
+            endStart = extractStart.substring(iBracket.e());
+        } else if (iSep.e() > -1) {
+            endStart = extractStart.substring(iSep.e());
+        } else {
+            endStart = extractStart;
+        }
+        return endStart;
+    }
+
+    private static Int2 getLastIndexOfOpenBracket(final String extractStart, final int start) {
+        final Int2 end = TextSearch.getDefaultSearch().lastIndexOf(extractStart, TemplateConstants.BRACKETS[1], start, TemplateConstants.SPEC, new String[][] { TemplateConstants.LITERAL });
+        final Int2 begin = TextSearch.getDefaultSearch().lastIndexOf(extractStart, TemplateConstants.BRACKETS[0], end.e() == -1 ? start : end.e(), TemplateConstants.SPEC,
+                new String[][] { TemplateConstants.LITERAL });
+        if (begin.b() > -1) {
+            return begin;
+        }
+        return Int2.NOT_FOUND;
+    }
+
+    /**
+     * Gets the completion's start.
+     * <p>
+     * Sample : "a.b.c.DDD" -> "a.b.c.DDD"
+     * 
+     * @param text
+     *            is the text
+     * @param originalOffset
+     *            is the offset within the text for which completions should be
+     *            computed
+     * @return the completion's start
+     */
+    // CHECKSTYLE:OFF this method comes from acceleo
+    private static String extractStart(final String originalText, final int originalOffset) {
+        if (originalOffset <= originalText.length()) {
+            final String prefix = "  "; //$NON-NLS-1$
+            final String text = prefix + originalText;
+            final int offset = prefix.length() + originalOffset;
+            int i = offset;
+            while (i >= 2) {
+                char c = text.charAt(i - 1);
+                if (TemplateConstants.FEATURE_BEGIN.equals(text.substring(i - TemplateConstants.FEATURE_BEGIN.length(), i))) {
+                    return TemplateConstants.FEATURE_BEGIN + text.substring(i, offset);
+                } else if (c == AcceleoCompletionEntry.PARENTHESIS[1]) { // (
+                                                                         // ...
+                                                                         // ) is
+                                                                         // a
+                                                                         // block
+                                                                         // to
+                    // ignore
+                    int level = 0;
+                    do {
+                        i--;
+                        c = text.charAt(i - 1);
+                        if (c == '"') {
+                            do {
+                                i--;
+                                c = text.charAt(i - 1);
+                                if (c == '"' && (i < 2 || text.charAt(i - 2) != '\\')) {
+                                    break;
+                                }
+                            } while (i > 1);
+                        } else if (c == AcceleoCompletionEntry.PARENTHESIS[1]) {
+                            level++;
+                        } else if (c == AcceleoCompletionEntry.PARENTHESIS[0]) {
+                            if (level == 0) {
+                                break;
+                            } else {
+                                level--;
+                            }
+                        }
+                    } while (i > 1);
+                } else if (c == AcceleoCompletionEntry.BRACKETS[1]) { // [ ... ]
+                                                                      // is a
+                                                                      // block
+                                                                      // to
+                    int level = 0;
+                    do {
+                        i--;
+                        c = text.charAt(i - 1);
+                        if (c == '"') {
+                            do {
+                                i--;
+                                c = text.charAt(i - 1);
+                                if (c == '"' && (i < 2 || text.charAt(i - 2) != '\\')) {
+                                    break;
+                                }
+                            } while (i > 1);
+                        } else if (c == AcceleoCompletionEntry.BRACKETS[1]) {
+                            level++;
+                        } else if (c == AcceleoCompletionEntry.BRACKETS[0]) {
+                            if (level == 0) {
+                                break;
+                            } else {
+                                level--;
+                            }
+                        }
+                    } while (i > 1);
+                } else {
+                    for (char element2 : AcceleoCompletionEntry.ACTIVATION_CHARACTERS) {
+                        if (c == element2) {
+                            return text.substring(i, offset);
+                        }
+                    }
+                }
+                i--;
+            }
+        }
+        return ""; //$NON-NLS-1$
+        // CHECKSTYLE:ON
+    }
+
+    private static String getDescription(final EClassifier eClassifier) {
+        String desc = null;
+        // Information come from GenModel.
+        // As the metamodel object of Acceleo loose this information, it doesn't
+        // do anything. Need to be fix.
+        final EAnnotation eAnno = eClassifier.getEAnnotation("http://www.eclipse.org/emf/2002/GenModel");
+        if (eAnno != null) {
+            desc = eAnno.getDetails().get("documentation"); //$NON-NLS-1$
+        }
+        if (desc == null) {
+            desc = eClassifier.getName();
+        }
+        return desc;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoExtendedInterpreter.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoExtendedInterpreter.java
new file mode 100644
index 0000000..a19f45b
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoExtendedInterpreter.java
@@ -0,0 +1,365 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
+import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterStatus;
+import org.eclipse.sirius.common.tools.api.util.StackEx;
+import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor;
+import org.eclipse.sirius.query.legacy.AcceleoInterpreterPlugin;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxExceptions;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalFailure;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.tools.classloaders.AcceleoClassLoader;
+import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoModuleProvider;
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+import com.google.common.collect.Sets;
+
+/**
+ * {@link AcceleoExtendedInterpreter} is able to evaluate Acceleo expression
+ * considering the possible metamodel extenders and using variables.
+ * 
+ * @author cbrun
+ */
+public class AcceleoExtendedInterpreter extends AcceleoInterpreter {
+
+    private static final boolean LOG_WARNINGS = false;
+
+    private static final String ACCELEO_PLUGIN_NAME = AcceleoInterpreterPlugin.getDefault().getBundle().getSymbolicName();
+
+    /**
+     * Class used to access the model data.
+     */
+    protected ModelAccessor accessor;
+
+    private ECrossReferenceAdapter crossReferencer;
+
+    /**
+     * All the representation description files (*.odesign) to to take into
+     * account.
+     */
+    private final List<File> representationDescriptionFiles;
+
+    /**
+     * Create a new {@link AcceleoExtendedInterpreter}. Be careful
+     * instantiating it this way, you should better use the File parameterized
+     * initializer to avoid class loader issues when evaluating your scripts.
+     */
+    public AcceleoExtendedInterpreter() {
+        super();
+        representationDescriptionFiles = new ArrayList<File>();
+    }
+
+    /**
+     * Create a new {@link AcceleoExtendedInterpreter} initialized with an
+     * accessor.. Be careful instantiating it this way, you should better use
+     * the File parameterized initializer to avoid class loader issues when
+     * evaluating your scripts.
+     * 
+     * @param accessor
+     *            a model accessor.
+     */
+    public AcceleoExtendedInterpreter(final ModelAccessor accessor) {
+        this();
+        this.accessor = accessor;
+    }
+
+    /**
+     * Create a new {@link AcceleoExtendedInterpreter} from an .air file.
+     * 
+     * @param representationDescriptionFile
+     *            any .odesign file, this file is used to initialize the class
+     *            loaders.
+     * @deprecated
+     */
+    @Deprecated
+    public AcceleoExtendedInterpreter(final File representationDescriptionFile) {
+        this();
+        representationDescriptionFiles.add(representationDescriptionFile);
+    }
+
+    /**
+     * Factory method for the new {@link SpecificScript} instances. Clients may
+     * override this method to provide new behaviors while evaluating Acceleo
+     * scripts.
+     * 
+     * @param current
+     *            current {@link EObject} used to create the script.
+     * @param mmURI
+     *            metamodel URI.
+     * @return the new instance of {@link SpecificScript}.
+     */
+    @Override
+    protected SpecificScript createNewScript(final EObject current, final String mmURI) {
+        File moreSpecificRepresentationDescriptionFile = representationDescriptionFiles != null && !representationDescriptionFiles.isEmpty() ? representationDescriptionFiles.get(0) : null;
+        /*
+         * If the interpreter has been created with no AIR file, then let's use
+         * the model one but then we will probably encounter issues with the
+         * services if the model is not in the same project as the AIR file.
+         */
+        if (moreSpecificRepresentationDescriptionFile == null && current != null && current.eResource() != null) {
+            // if the resource associated to current is a CDOResource
+            // we obviously can't get any IFile related to this element
+            // to avoid any dependency to CDO, we catch the exception raised by
+            // getIFile
+            try {
+
+                if (current.eResource().getURI().path() != null && Resources.getIFile(current.eResource()) != null && Resources.getIFile(current.eResource()).getLocation() != null) {
+                    moreSpecificRepresentationDescriptionFile = Resources.getIFile(current.eResource()).getLocation().toFile();
+                }
+            } catch (IllegalArgumentException e) {
+                // The assertion in
+                // org.eclipse.core.internal.resources.Workspace.newResource()
+                // -> case IFIle (line 1801), can raise an error
+
+                // We don't have to treat this exception, the
+                // moreSpecificRepresentationDescriptionFile will be left to his
+                // default value
+            }
+        }
+
+        /*
+         * We need to set the preferred loader here in order to
+         * have Acceleo remember which class loader was used to create the
+         * script so as to avoid LinkageErrors. It will be reverted back to null
+         * at the end of this method. IMPORTANT : the preferred class loader
+         * MUST be set everywhere we instantiate or evaluate a SpecificScript.
+         * See AcceleoInterpreter#evaluate(EObject, String) and
+         * SiriusInformationAdapter#getAdapter(Object, Class).
+         */
+        if (current != null) {
+            AcceleoClassLoader.setPreferredClassLoader(current.getClass().getClassLoader());
+        }
+        final SmartSpecificScript newScript = new SmartSpecificScript(moreSpecificRepresentationDescriptionFile, representationDescriptionFiles, this);
+        newScript.setCrossReferencer(crossReferencer);
+        try {
+            final String templateHeader = getScriptHeader(mmURI);
+            newScript.reset(templateHeader);
+        } catch (final TemplateSyntaxExceptions e) {
+            AcceleoInterpreterPlugin.getDefault().error("Syntax error in template while initializing the interpreter.", e);
+        }
+        AcceleoClassLoader.setPreferredClassLoader(null);
+        return newScript;
+    }
+
+    /**
+     * Evaluate the Acceleo expression.
+     * 
+     * @param eObj
+     *            instance on which the Expression should be evaluated.
+     * @param expression
+     *            Acceleo expression to evaluate.
+     * @throws EvaluationException
+     *             on error concerning ENode.
+     * @return the result of the Expression.
+     */
+    @Override
+    public Object evaluate(final EObject eObj, final String expression) throws EvaluationException {
+        // Save the original output
+        final PrintStream originalOut = System.out;
+        ENode result = null;
+        result = doEvaluate(eObj, expression);
+        // Restore the original output (because it is catched by Acceleo)
+        if (originalOut != System.out) {
+            System.setOut(originalOut);
+        }
+        return getValue(result, expression);
+    }
+
+    @SuppressWarnings("unused")
+    private ENode doEvaluate(final EObject eObj, final String expression) throws EvaluationException {
+        ENodeException.disableRuntimeMarkersFor(eObj);
+
+        final ENode result = super.evaluateENode(eObj, expression);
+
+        try {
+            //
+            // log eNode error if the profiler is active.
+            if (AcceleoExtendedInterpreter.LOG_WARNINGS && !result.log().isOk()) {
+                final MultiStatus status = new MultiStatus(AcceleoExtendedInterpreter.ACCELEO_PLUGIN_NAME, IStatus.INFO, "variables info", null);
+                final Iterator<Entry<String, StackEx<ENode>>> iterVariables = variableTables.entrySet().iterator();
+                while (iterVariables.hasNext()) {
+                    final Entry<String, StackEx<ENode>> entry = iterVariables.next();
+                    final String variableName = entry.getKey();
+                    final Object variableValue = getVariableValue(variableName);
+                    final IStatus subStatus = new Status(IStatus.INFO, AcceleoExtendedInterpreter.ACCELEO_PLUGIN_NAME, variableName + " : " + String.valueOf(variableValue));
+                    status.add(subStatus);
+                }
+                final IStatus evaluationStatus = new Status(IStatus.INFO, AcceleoExtendedInterpreter.ACCELEO_PLUGIN_NAME, "expression : " + expression);
+                status.add(evaluationStatus);
+                final IStatus contextStatus = new Status(IStatus.INFO, AcceleoExtendedInterpreter.ACCELEO_PLUGIN_NAME, "context : " + eObj);
+                status.add(contextStatus);
+                AcceleoInterpreterPlugin.getDefault().logENode(result, status);
+            }
+        } finally {
+            ENodeException.enableRuntimeMarkersFor(eObj);
+        }
+        if (result.log().allErrors().hasNext()) {
+            final EvalFailure evalFailure = (EvalFailure) result.log().allErrors().next();
+            if (isMessageToThrow(evalFailure.getMessage())) {
+                throw new EvaluationException(evalFailure.getMessage());
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Throw all the message except those corresponding to
+     * EmptyFeatureEvaluation
+     * 
+     * @param message
+     *            The message to test
+     * @return false if the message corresponds to EmptyFeatureEvaluation, true
+     *         otherwise
+     */
+    private boolean isMessageToThrow(final String message) {
+        final String evalFormater = AcceleoGenMessages.getString("EvalFailure.FailureMessage");
+        final String evalPrefix = MessageFormat.format(evalFormater, "");
+        if (message != null && message.startsWith(evalPrefix)) {
+            final String endOfMessage = message.substring(evalPrefix.length());
+            if (endOfMessage.startsWith(AcceleoGenMessages.getString("ENodeError.EmptyEvaluation"))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.business.internal.interpreter.AcceleoInterpreter#setModelAccessor(org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor)
+     */
+    @Override
+    public void setModelAccessor(final ModelAccessor modelAccessor) {
+        this.accessor = modelAccessor;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.business.internal.interpreter.AcceleoInterpreter#createInterpreter()
+     */
+    @Override
+    public IInterpreter createInterpreter() {
+        return new AcceleoExtendedInterpreter();
+    }
+
+    /**
+     * 
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.business.internal.interpreter.AcceleoInterpreter#setProperty(java.lang.Object,
+     *      java.lang.Object)
+     */
+    @Override
+    public void setProperty(final Object key, final Object value) {
+        if (IInterpreter.FILES.equals(key)) {
+            if (value instanceof List) {
+                @SuppressWarnings("unchecked")
+                final List<String> odesignPaths = (List<String>) value;
+                for (String odesignPath : odesignPaths) {
+                    // Add this file to the list of odesignFiles
+                    File file = AcceleoModuleProvider.getDefault().getFile(new Path(odesignPath));
+                    if (file != null) {
+                        this.representationDescriptionFiles.add(file);
+                    }
+                }
+            } else if (value == null) {
+                this.representationDescriptionFiles.clear();
+            }
+        }
+        super.setProperty(key, value);
+    }
+
+    /**
+     * 
+     * {@inheritDoc}
+     */
+    @Override
+    public void setCrossReferencer(final ECrossReferenceAdapter crossReferencer) {
+        this.crossReferencer = crossReferencer;
+        if (crossReferencer != null) {
+            for (final SpecificScript script : mmToScript.values()) {
+                if (script instanceof SmartSpecificScript) {
+                    ((SmartSpecificScript) script).setCrossReferencer(crossReferencer);
+                }
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.business.internal.interpreter.AcceleoInterpreter#getCompletionEntry()
+     */
+    @Override
+    protected AcceleoCompletionEntry getCompletionEntry() {
+        return new AcceleoCompletionEntry() {
+            @Override
+            protected void addModelElements(Object[] proposals, List<Object> contents) {
+                if (element != null && accessor != null && accessor.eInstanceOf(element, "tool.ModelOperation")) {
+                    /*
+                     * if we are on a tool, then we do not need to provide
+                     * semantic model element in completion
+                     */
+                } else {
+                    super.addModelElements(proposals, contents);
+                }
+            }
+        };
+    }
+
+    /**
+     * 
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#validateExpression(java.lang.String,
+     *      java.lang.String)
+     */
+    public Collection<IInterpreterStatus> validateExpression(IInterpreterContext context, String expression) {
+        // Acceleo 2 is not able to analyse this expression if no target is
+        // given
+        return Sets.newLinkedHashSet();
+    }
+
+    /**
+     * 
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#supportsValidation()
+     */
+    public boolean supportsValidation() {
+        return false;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoInterpreter.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoInterpreter.java
new file mode 100644
index 0000000..c1b2dbc
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoInterpreter.java
@@ -0,0 +1,1026 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentContext;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentInstanceContext;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentProposal;
+import org.eclipse.sirius.common.tools.api.contentassist.IProposalProvider;
+import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterProvider;
+import org.eclipse.sirius.common.tools.api.interpreter.IVariableStatusListener;
+import org.eclipse.sirius.common.tools.api.util.StackEx;
+import org.eclipse.sirius.ecore.extender.business.api.accessor.MetamodelDescriptor;
+import org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor;
+import org.eclipse.sirius.query.legacy.AcceleoInterpreterPlugin;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.Template;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateElement;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.tools.classloaders.AcceleoClassLoader;
+
+/**
+ * This utility class ease the evaluation of Acceleo expressions. A singleton
+ * instance is available for pure API comfort but it is advised for performances
+ * issues to avoid changing metamodel on consecutive evaluations.
+ * 
+ * @author cbrun
+ * 
+ */
+// CHECKSTYLE:OFF
+public abstract class AcceleoInterpreter implements IInterpreter, IInterpreterProvider, IProposalProvider {
+    // CHECKSTYLE:ON
+    /**
+     * Keyword used to identify a variable.
+     */
+    protected static final String VARIABLE_KEYWORD = "$";
+
+    /**
+     * Keyword used to identify the start of an expression.
+     */
+    protected static final String PREFIX_KEYWORD = "<%";
+
+    /**
+     * Keyword used to identify the end of an expression.
+     */
+    protected static final String SUFFIX_KEYWORD = "%>";
+
+    /** This will allow us to store the parsed templates for each expressions. */
+    protected final Map<SpecificScript, Map<String, Template>> templates = new HashMap<SpecificScript, Map<String, Template>>();
+
+    /**
+     * Script instance.
+     */
+    protected SpecificScript pvScript;
+
+    /**
+     * Table keeping track of the variables values.
+     */
+    protected final Map<String, StackEx<ENode>> variableTables = new HashMap<String, StackEx<ENode>>();
+
+    /**
+     * Map used to keep track of the Scripts instances from a metamodel URI.
+     */
+    protected Map<String, SpecificScript> mmToScript = new WeakHashMap<String, SpecificScript>();
+
+    private final Collection<String> imports = new LinkedHashSet<String>();
+
+    private final Set<IVariableStatusListener> variablesListeners = new HashSet<IVariableStatusListener>();
+
+    /** The optional cache. */
+    private Map<CacheKey, ENode> cache;
+
+    private AcceleoTemplateWorkspaceListener templateListener;
+
+    /**
+     * Constructor.
+     */
+    public AcceleoInterpreter() {
+        installWorkspaceListener();
+    }
+
+    /**
+     * Return a script able to evaluate expression on the given EObject.
+     * 
+     * @param current
+     *            current {@link EObject}.
+     * @return a script able to evaluate expression on the given EObject.
+     */
+    protected final SpecificScript getScript(final EObject current) {
+        /*
+         * we keep one script per metamodel.
+         */
+        final String mmURI = computeMetamodelURI(current);
+        final SpecificScript resultScript = mmToScript.get(mmURI);
+        if (resultScript != null)
+            return resultScript;
+        final SpecificScript newScript = createNewScript(current, mmURI);
+        mmToScript.put(mmURI, newScript);
+        return newScript;
+    }
+
+    /**
+     * 
+     * {@inheritDoc}
+     */
+    protected abstract SpecificScript createNewScript(final EObject current, final String mmURI);
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluate(org.eclipse.emf.ecore.EObject,
+     *      java.lang.String)
+     */
+    public Object evaluate(final EObject target, final String expression) throws EvaluationException {
+        final ENode node = evaluateENode(target, expression);
+        return getValue(node, expression);
+    }
+
+    /**
+     * Evaluate the given expression and return the result.
+     * 
+     * @param eObj
+     *            : the EObject on which we want to apply the evaluation.
+     * @param expression
+     *            : the Acceleo expression to evaluate, something like
+     *            "<%eContainer()%>" but may also be "name : <%name%>".
+     * @return : the {@link ENode} corresponding to this evaluation, and
+     *         {@link ENode} wrap any possible type Acceleo may use.
+     * @throws EvaluationException
+     *             on evaluation errors.
+     */
+    public ENode evaluateENode(final EObject eObj, final String expression) throws EvaluationException {
+        try {
+            /*
+             * We need to set the preferred loader here in order
+             * to have Acceleo use the same class loader to create and evaluate
+             * the script so as to avoid LinkageErrors. It will be reverted back
+             * to null post-evaluation. IMPORTANT : the preferred class loader
+             * MUST be set everywhere we instantiate or evaluate a
+             * SpecificScript. See
+             * AcceleoExtendedInterpreter#createNewScript(EObject, String) and
+             * SiriusInformationAdapter#getAdapter(Object, Class).
+             */
+            AcceleoClassLoader.setPreferredClassLoader(eObj.getClass().getClassLoader());
+            final SpecificScript script = getScript(eObj);
+            Template template = null;
+            if (expression != null && expression.trim().length() > 0) {
+                Map<String, Template> scriptTemplates = templates.get(script);
+                if (scriptTemplates != null && scriptTemplates.containsKey(expression)) {
+                    template = scriptTemplates.get(expression);
+                } else {
+                    template = Template.from(expression, script, eObj);
+                    if (scriptTemplates == null) {
+                        scriptTemplates = new WeakHashMap<String, Template>();
+                        templates.put(script, scriptTemplates);
+                    }
+                    scriptTemplates.put(expression, template);
+                }
+            }
+            if (template != null)
+                return template.evaluate(eObj, LaunchManager.create("run", false));
+            AcceleoClassLoader.setPreferredClassLoader(null);
+            return new ENode(null, (TemplateElement) null, true);
+        } catch (final ENodeException e) {
+            throw new EvaluationException(e);
+        } catch (final FactoryException e) {
+            throw new EvaluationException(e);
+        }
+    }
+
+    /**
+     * Evaluate an acceleo condition. The result is <code>true</code> if the
+     * evaluation returns a <code>true</code> value or if the evaluation returns
+     * a non null object. If the condition is null or empty or only composed
+     * with white spaces, the result is <code>true</code>.
+     * 
+     * @param eObj
+     *            the context object.
+     * @param condition
+     *            the condition to test.
+     * @return <code>true</code> if the evaluation returns a <code>true</code>
+     *         value or if the evaluation returns a non null object or if the
+     *         condition is empty.
+     * @throws EvaluationException
+     *             if the interpreter encounter a problem while evaluting the
+     *             condition.
+     * @deprecated use {@link AcceleoInterpreter#evaluate(EObject, String)}
+     *             instead
+     */
+    @Deprecated
+    public boolean evaluateCondition(final EObject eObj, final String condition) throws EvaluationException {
+        final boolean preconditionAccepted = true;
+        return preconditionAccepted;
+    }
+
+    /**
+     * return the header of the script containing the imports.
+     * 
+     * @param metamodelURI
+     *            the metamodel uri.
+     * @return the header of the script containing the imports.
+     */
+    protected String getScriptHeader(final String metamodelURI) {
+        final String carriage = "\n";
+        final StringBuffer header = new StringBuffer("");
+        header.append(TemplateConstants.IMPORT_BEGIN).append(carriage);
+        header.append(TemplateConstants.MODELTYPE_WORD).append(' ').append(metamodelURI).append(" \n");
+        final Iterator<String> it = imports.iterator();
+        while (it.hasNext()) {
+            final String imp = it.next();
+            if (!imp.contains("::")) {
+                // Don't try to import Acceleo 3 modules.
+                header.append(TemplateConstants.IMPORT_WORD).append(' ').append(imp).append(carriage);
+            }
+        }
+        header.append(carriage).append(TemplateConstants.IMPORT_END);
+        return header.toString();
+    }
+
+    /**
+     * Gets the URI of the metamodel that defines the given object.
+     * 
+     * @param object
+     *            is an object of the model
+     * @return the URI of the metamodel
+     */
+    protected String computeMetamodelURI(final EObject object) {
+        if (isDynamic(object)) {
+            return computeEcoreFileURI(object);
+        } else {
+            return computeNsURI(object);
+        }
+    }
+
+    private String computeEcoreFileURI(final EObject object) {
+        final Resource eCoreRes = object.eClass().eResource();
+        if (eCoreRes != null && eCoreRes.getURI() != null) {
+            final URI ecoreURI = eCoreRes.getURI();
+            if (ecoreURI.isPlatformResource()) {
+                return ecoreURI.toPlatformString(true);
+            }
+        }
+        return null;
+    }
+
+    private boolean isDynamic(final EObject object) {
+        return object instanceof DynamicEObjectImpl;
+    }
+
+    private String computeNsURI(final EObject object) {
+        EPackage p = object.eClass().getEPackage();
+        String nsURI = p.getNsURI();
+        p = p.getESuperPackage();
+        while (p != null) {
+            final String currentURI = p.getNsURI();
+            if (currentURI != null && currentURI.length() > 0 && !currentURI.startsWith("unused://")) {
+                nsURI = currentURI;
+            }
+            p = p.getESuperPackage();
+        }
+        return nsURI;
+    }
+
+    /**
+     * Set a variable in the current interpreter. The user will be able to
+     * access the variable value using the "$" prefix.
+     * 
+     * @param name
+     *            the variable name.
+     * @param value
+     *            the variable value.
+     */
+    public void setVariable(final String name, final EObject value) {
+        setVariable(name, new ENode(value, (TemplateElement) null, true));
+    }
+
+    /**
+     * Set a variable in the current interpreter. The user will be able to
+     * access the variable value using the "$" prefix.
+     * 
+     * @param name
+     *            the variable name.
+     * @param value
+     *            the variable value.
+     */
+    public void setVariable(final String name, final Object value) {
+        final ENode valueNode = ENode.createTry(value, new ENode(null, (TemplateElement) null, true));
+        setVariable(name, valueNode);
+    }
+
+    /**
+     * Set a variable in the current interpreter. The user will be able to
+     * access the variable value using the "$" prefix.
+     * 
+     * @param name
+     *            the variable name.
+     * @param value
+     *            the variable value.
+     */
+    public void setVariable(final String name, final ENode value) {
+        StackEx<ENode> values = variableTables.get(name);
+        if (values == null) {
+            values = new StackEx<ENode>();
+        }
+        values.push(value);
+        variableTables.put(name, values);
+        notifyVariableListeners();
+    }
+
+    /**
+     * Unset the variable.
+     * 
+     * @param name
+     *            the variable name.
+     */
+    public void unSetVariable(final String name) {
+        final StackEx<ENode> values = variableTables.get(name);
+        if (values != null) {
+            if (values.size() > 1) {
+                /*
+                 * There is another value in the stack, let's pop the old one.
+                 */
+                values.pop();
+            } else {
+                /*
+                 * It was the last value in the stack, let's clear this variable
+                 * entry.
+                 */
+                clearVariable(name);
+            }
+        }
+        notifyVariableListeners();
+    }
+
+    /**
+     * return the variable value.
+     * 
+     * @param name
+     *            the variable name.
+     * @return the variable value.
+     */
+    protected ENode getVariableValue(final String name) {
+        final StackEx<ENode> values = variableTables.get(name);
+        if (values != null)
+            return values.peek();
+        return null;
+    }
+
+    /**
+     * Check if the variable is set.
+     * 
+     * @param name
+     *            the variable name
+     * @return <code>true</code> is the variable is set, <code>false</code>
+     *         otherwise
+     */
+    protected boolean isVariableSet(final String name) {
+        return variableTables.containsKey(name);
+    }
+
+    /**
+     * Clear all the variables of the interpreter.
+     */
+    public void clearVariables() {
+        variableTables.clear();
+        notifyVariableListeners();
+    }
+
+    /**
+     * Clear the variable with the given name.
+     * 
+     * @param name
+     *            : name of the variable to clear.
+     */
+    public void clearVariable(final String name) {
+        if (variableTables.containsKey(name)) {
+            variableTables.remove(name);
+            notifyVariableListeners();
+        }
+    }
+
+    /**
+     * Clear all the imports.
+     */
+    public void clearImports() {
+        mmToScript.clear();
+        templates.clear();
+        imports.clear();
+    }
+
+    /**
+     * Import a Java service or a template in the current Interpreter.
+     * 
+     * @param path
+     *            the import id, for instance
+     *            <tt>fr.obeo.my.package.java.StringServices</tt>
+     */
+    public void addImport(final String path) {
+        if (path != null && path.contains(".") && !imports.contains(path)) {
+            mmToScript.clear();
+            templates.clear();
+            imports.add(path);
+        }
+        templates.clear();
+    }
+
+    /**
+     * Add a new listener to the current interpreter, the listener will be
+     * notified on changes concerning variables.
+     * 
+     * @param newListener
+     *            the new listener to add.
+     */
+    public void addVariableStatusListener(final IVariableStatusListener newListener) {
+        variablesListeners.add(newListener);
+    }
+
+    /**
+     * Remove the given {@link IVariableStatusListener}.
+     * 
+     * @param listener
+     *            listener to remove.
+     */
+    public void removeVariableStatusListener(final IVariableStatusListener listener) {
+        variablesListeners.remove(listener);
+    }
+
+    /**
+     * Map with the variables.
+     * 
+     * @return a map containing the current variables.
+     */
+    public Map<String, ?> getVariables() {
+        final Map<String, ENode> lightVariables = new HashMap<String, ENode>();
+        final Iterator<String> it = variableTables.keySet().iterator();
+        while (it.hasNext()) {
+            final String variableName = it.next();
+            lightVariables.put(variableName, getVariableValue(variableName));
+        }
+        return lightVariables;
+    }
+
+    private void notifyVariableListeners() {
+        if (variablesListeners.size() > 0) {
+            final Map<String, ?> lightVariables = getVariables();
+            final Iterator<IVariableStatusListener> it = variablesListeners.iterator();
+            while (it.hasNext()) {
+                final IVariableStatusListener listener = it.next();
+                listener.notifyChanged(lightVariables);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateBoolean(EObject,
+     *      String)
+     */
+    @Deprecated
+    public boolean getAsBoolean(final Object evaluate) {
+        return internalGetAsBoolean(evaluate);
+    }
+
+    private boolean internalGetAsBoolean(final Object evaluate) {
+        boolean result = false;
+        if (evaluate instanceof ENode) {
+            result = ENodeHelper.getAsBoolean((ENode) evaluate);
+        } else if (evaluate instanceof Boolean) {
+            result = ((Boolean) evaluate).booleanValue();
+        } else if (evaluate instanceof String) {
+            result = Boolean.parseBoolean((String) evaluate);
+        } else if (evaluate instanceof IAdaptable) {
+            final Boolean adaptedBoolean = (Boolean) ((IAdaptable) evaluate).getAdapter(Boolean.class);
+            if (adaptedBoolean != null)
+                result = adaptedBoolean.booleanValue();
+        } else if (evaluate != null) {
+            // in acceleo, if (something) returns true
+            result = true;
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateEObject(EObject,
+     *      String)
+     */
+    @Deprecated
+    public EObject getAsEObject(final Object result) {
+        return internalGetAsEObject(result);
+    }
+
+    private EObject internalGetAsEObject(final Object result) {
+        EObject eObject = null;
+        if (result instanceof ENode) {
+            eObject = ENodeHelper.getAsEObject((ENode) result);
+        } else if (result instanceof EObject) {
+            eObject = (EObject) result;
+        } else if (result instanceof IAdaptable) {
+            eObject = (EObject) ((IAdaptable) result).getAdapter(EObject.class);
+        } else if (result instanceof ENodeList) {
+            final ENodeList eNodeList = (ENodeList) result;
+            if (eNodeList.size() > 0) {
+                eObject = internalGetAsEObject(eNodeList.get(0));
+            }
+        } else if (result instanceof Collection) {
+            final Collection<?> collection = (Collection<?>) result;
+            if (!collection.isEmpty()) {
+                final Object first = collection.iterator().next();
+                eObject = internalGetAsEObject(first);
+            }
+        }
+        return eObject;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateInteger(EObject,
+     *      String)
+     */
+    @Deprecated
+    public Integer getAsInteger(final Object result) {
+        return internalGetAsInteger(result);
+    }
+
+    private Integer internalGetAsInteger(final Object result) {
+        Integer integer = null;
+        if (result instanceof ENode) {
+            integer = ENodeHelper.getAsInteger((ENode) result);
+        } else if (result instanceof Integer) {
+            integer = (Integer) result;
+        } else if (result instanceof IAdaptable) {
+            integer = (Integer) ((IAdaptable) result).getAdapter(Integer.class);
+        } else if (result instanceof String) {
+            try {
+                final int res = Integer.parseInt((String) result);
+                integer = Integer.valueOf(res);
+            } catch (final NumberFormatException e) {
+                // silent
+            }
+        }
+        return integer;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateBoolean(EObject,
+     *      String)
+     */
+    @Deprecated
+    public Collection<EObject> getAsListOfEObjects(final Object object) {
+        return internalGetAsListOfEObjects(object);
+    }
+
+    private Collection<EObject> internalGetAsListOfEObjects(final Object object) {
+        Collection<EObject> result = new LinkedList<EObject>();
+        if (object instanceof Collection) {
+            final Collection<?> tmp = (Collection<?>) object;
+            for (final Object obj : tmp) {
+                if (obj instanceof EObject) {
+                    result.add((EObject) obj);
+                }
+            }
+        } else if (object instanceof ENode) {
+            result = ENodeHelper.getAsListOfEObjects((ENode) object);
+        } else if (object instanceof EObject) {
+            result.add((EObject) object);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateString(EObject,
+     *      String)
+     */
+    @Deprecated
+    public String getAsString(final Object result) {
+        return internalGetAsString(result);
+    }
+
+    private String internalGetAsString(final Object result) {
+        if (result instanceof ENode) {
+            return ENodeHelper.getAsString((ENode) result);
+        }
+        return result != null ? result.toString() : null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#getValue(java.lang.Object,
+     *      java.lang.String)
+     */
+    public Object getValue(final Object object, final String s) {
+        Object result = object;
+        if (object instanceof ENode) {
+            result = ENodeHelper.getValue((ENode) result, s);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#provides(java.lang.String)
+     */
+    public boolean provides(final String expression) {
+        return expression != null && expression.indexOf(PREFIX_KEYWORD) >= 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateBoolean(org.eclipse.emf.ecore.EObject,
+     *      java.lang.String)
+     */
+    public boolean evaluateBoolean(final EObject context, final String expression) throws EvaluationException {
+        final Object evaluation = evaluate(context, expression);
+        return internalGetAsBoolean(evaluation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateCollection(org.eclipse.emf.ecore.EObject,
+     *      java.lang.String)
+     */
+    public Collection<EObject> evaluateCollection(final EObject context, final String expression) throws EvaluationException {
+        final Object evaluation = evaluate(context, expression);
+        return internalGetAsListOfEObjects(evaluation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateEObject(org.eclipse.emf.ecore.EObject,
+     *      java.lang.String)
+     */
+    public EObject evaluateEObject(final EObject context, final String expression) throws EvaluationException {
+        final Object evaluation = evaluate(context, expression);
+        return internalGetAsEObject(evaluation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateInteger(org.eclipse.emf.ecore.EObject,
+     *      java.lang.String)
+     */
+    public Integer evaluateInteger(final EObject context, final String expression) throws EvaluationException {
+        final Object evaluation = evaluate(context, expression);
+        return internalGetAsInteger(evaluation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#evaluateString(org.eclipse.emf.ecore.EObject,
+     *      java.lang.String)
+     */
+    public String evaluateString(final EObject context, final String expression) throws EvaluationException {
+        final Object evaluation = evaluate(context, expression);
+        return internalGetAsString(evaluation);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#getVariable(java.lang.String)
+     */
+    public Object getVariable(final String name) {
+        final ENode node = getVariableValue(name);
+        return getValue(node, "");
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#setProperty(java.lang.Object,
+     *      java.lang.Object)
+     */
+    public void setProperty(final Object key, final Object value) {
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#dispose()
+     */
+    public void dispose() {
+        for (final Map.Entry<SpecificScript, Map<String, Template>> child : templates.entrySet())
+            child.getValue().clear();
+        templates.clear();
+        this.variableTables.clear();
+        this.variablesListeners.clear();
+        this.imports.clear();
+        this.deactivateCache();
+        uninstallWorkspaceListener();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#setModelAccessor(org.eclipse.sirius.ecore.extender.business.api.accessor.ModelAccessor)
+     */
+    public void setModelAccessor(final ModelAccessor modelAccessor) {
+        // ignore.
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreterProvider#createInterpreter()
+     */
+    public abstract IInterpreter createInterpreter();
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.contentassist.IProposalProvider#getProposals(org.eclipse.sirius.common.tools.api.interpreter.IInterpreter,
+     *      org.eclipse.sirius.common.tools.api.contentassist.ContentContext)
+     */
+    public List<ContentProposal> getProposals(IInterpreter interpreter, ContentContext context) {
+        return getCompletionEntry().computeProposals(context);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#getPrefix()
+     */
+    public String getPrefix() {
+        return PREFIX_KEYWORD;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#getNewEmtpyExpression()
+     */
+    public ContentProposal getNewEmtpyExpression() {
+        return new ContentProposal(PREFIX_KEYWORD + SUFFIX_KEYWORD, PREFIX_KEYWORD + SUFFIX_KEYWORD, "New legacy query language expression.", 2);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#getVariablePrefix()
+     */
+    public String getVariablePrefix() {
+        return VARIABLE_KEYWORD;
+    }
+
+    /**
+     * 
+     * {@inheritDoc}
+     */
+    public void setCrossReferencer(final ECrossReferenceAdapter crossReferencer) {
+        // no handling of cross referencer with specific script. (yet ;) )
+    }
+
+    /**
+     * Returns the result of the evaluation from the cache.
+     * 
+     * @param context
+     *            the context of the evaluation.
+     * @param evaluation
+     *            the evaluation.
+     * @param args
+     *            the arguments of the evaluation.
+     * @return the result of the evaluation from the cache.
+     */
+    protected ENode getFromCache(final ENode context, final String evaluation, final ENode[] args) {
+        if (cache != null) {
+            return cache.get(new CacheKey(context, evaluation, args));
+        }
+        return null;
+    }
+
+    /**
+     * Caches an evaluation.
+     * 
+     * @param context
+     *            the context.
+     * @param evaluation
+     *            the evaluation.
+     * @param args
+     *            the arguments of the evaluation.
+     * @param result
+     *            the result of the evaluation.
+     */
+    protected void cache(final ENode context, final String evaluation, final ENode[] args, final ENode result) {
+        if (cache != null)
+            cache.put(new CacheKey(context, evaluation, args), result);
+    }
+
+    /**
+     * Activates the cache.
+     */
+    public void activateCache() {
+        if (this.cache == null)
+            this.cache = new HashMap<CacheKey, ENode>();
+    }
+    
+    /**
+     * {@inheritDoc}
+     *
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#activateMetamodels(java.util.Collection)
+     */
+    public void activateMetamodels(Collection<MetamodelDescriptor> metamodels) {
+        // Nothing to do
+    }
+
+    /**
+     * Deactivates the cache.
+     */
+    public void deactivateCache() {
+        if (this.cache != null) {
+            this.cache.clear();
+            this.cache = null;
+        }
+    }
+
+    /**
+     * Inner Class CacheKey
+     */
+    private static class CacheKey {
+
+        private ENode context;
+
+        private String evaluation;
+
+        private ENode[] args;
+
+        public CacheKey(final ENode context, final String evaluation, final ENode[] args) {
+            this.context = context;
+            this.evaluation = evaluation;
+            this.args = args;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + (evaluation == null ? 0 : evaluation.hashCode());
+            result = prime * result + (context == null ? 0 : hashCode(context));
+            for (ENode node : args) {
+                result = prime * result + (node == null ? 0 : hashCode(node));
+            }
+            return result;
+        }
+
+        private int hashCode(final ENode node) {
+            int value = 0;
+            if (node.getValue() != null) {
+                if (!node.isList()) {
+                    return node.getValue().hashCode();
+                } else {
+                    try {
+                        final ENodeIterator iterNodes = node.getList().iterator();
+                        while (iterNodes.hasNext()) {
+                            value += hashCode(iterNodes.next());
+                        }
+                    } catch (final ENodeCastException e) {
+                        AcceleoInterpreterPlugin.getDefault().error(e.getMessage(), e);
+                    }
+                }
+            }
+            return value;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(final Object obj) {
+            boolean result = false;
+            if (obj instanceof CacheKey) {
+                result = equals((CacheKey) obj);
+            }
+            return result;
+        }
+
+        private boolean equals(final CacheKey cacheKey) {
+            final boolean node = (this.context == null && cacheKey.context == null) || (this.context != null && this.context.equals((Object) cacheKey.context));
+            final boolean eval = node && ((this.evaluation == null && cacheKey.evaluation == null) || (this.evaluation != null && this.evaluation.equals(cacheKey.evaluation)));
+            boolean result = eval && this.args.length == cacheKey.args.length;
+            for (int i = 0; i < args.length && result; i++) {
+                result = this.args[i].equals((Object) cacheKey.args[i]);
+            }
+            return result;
+        }
+
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.contentassist.IProposalProvider#getProposals(org.eclipse.sirius.common.tools.api.interpreter.IInterpreter,
+     *      org.eclipse.sirius.common.tools.api.contentassist.ContentInstanceContext)
+     */
+    public List<ContentProposal> getProposals(IInterpreter interpreter, ContentInstanceContext context) {
+        final String textSoFar = context.getTextSoFar();
+        String evaluationString = textSoFar.substring(0, context.getCursorPosition());
+
+        if (evaluationString.toLowerCase().startsWith(PREFIX_KEYWORD)) {
+            // Ask AcceleoCompletionEntry for proposals and process them
+            List<ContentProposal> resultList = getCompletionEntry().computeProposals(context);
+            if (resultList.size() > 0) {
+                return resultList;
+            }
+        }
+
+        return Collections.emptyList();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#getImports()
+     */
+    public Collection<String> getImports() {
+        return Collections.<String> unmodifiableCollection(this.imports);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreter#removeImport(String)
+     */
+    public void removeImport(String dependency) {
+        if (this.imports.contains(dependency)) {
+            this.imports.remove(dependency);
+            mmToScript.clear();
+        }
+        templates.clear();
+    }
+
+    protected AcceleoCompletionEntry getCompletionEntry() {
+        return new AcceleoCompletionEntry();
+    }
+
+    /**
+     * install workspace listener
+     */
+    private void installWorkspaceListener() {
+        if (templateListener == null) {
+            templateListener = new AcceleoTemplateWorkspaceListener(this);
+            final IWorkspace workspace = ResourcesPlugin.getWorkspace();
+            workspace.addResourceChangeListener(templateListener);
+        }
+    }
+
+    /**
+     * uninstall workspace listener.
+     */
+    private void uninstallWorkspaceListener() {
+        if (templateListener != null) {
+            final IWorkspace workspace = ResourcesPlugin.getWorkspace();
+            workspace.removeResourceChangeListener(templateListener);
+            templateListener = null;
+        }
+    }
+
+    /**
+     * Clear templates stored.
+     */
+    protected void reconsiderTemplateFiles() {
+        for (final Map.Entry<SpecificScript, Map<String, Template>> child : templates.entrySet())
+            child.getValue().clear();
+
+        mmToScript.clear();
+        templates.clear();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoInterpreterProvider.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoInterpreterProvider.java
new file mode 100644
index 0000000..44b1f00
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoInterpreterProvider.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterProvider;
+
+/**
+ * Provides Acceleo interpreter.
+ * 
+ * @author ymortier
+ */
+public class AcceleoInterpreterProvider implements IInterpreterProvider {
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreterProvider#createInterpreter()
+     */
+    public IInterpreter createInterpreter() {
+        return new AcceleoExtendedInterpreter();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.common.tools.api.interpreter.IInterpreterProvider#provides(java.lang.String)
+     */
+    public boolean provides(final String expression) {
+        return expression != null && expression.indexOf(AcceleoInterpreter.PREFIX_KEYWORD) > 0;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoTemplateWorkspaceListener.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoTemplateWorkspaceListener.java
new file mode 100644
index 0000000..ea5bf90
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/AcceleoTemplateWorkspaceListener.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.sirius.common.tools.api.resource.FileProvider;
+
+/**
+ * Workspace resource listener.
+ * 
+ * @author cnotot
+ */
+public class AcceleoTemplateWorkspaceListener implements IResourceChangeListener {
+
+    private AcceleoInterpreter interpreter;
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param interpreter
+     *            the interpreter
+     */
+    public AcceleoTemplateWorkspaceListener(final AcceleoInterpreter interpreter) {
+        this.interpreter = interpreter;
+    }
+
+    /**
+     * resourceChanged.
+     * 
+     * @param event
+     *            {@link IResourceChangeListener}
+     */
+    public void resourceChanged(final IResourceChangeEvent event) {
+
+        final IResourceDelta delta = event.getDelta();
+
+        if (delta != null && hasAtLeastOneModifiedTemplate(delta)) {
+            processDelta(delta);
+        }
+
+    }
+
+    private boolean hasAtLeastOneModifiedTemplate(IResourceDelta delta) {
+        for (IResourceDelta deltaChild : delta.getAffectedChildren()) {
+            if (isAboutFolderDerived(deltaChild)) {
+                break;
+            } else if (isAboutTemplateChange(deltaChild) || hasAtLeastOneModifiedTemplate(deltaChild)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isAboutFolderDerived(final IResourceDelta delta) {
+        return delta.getResource().getType() == IResource.FOLDER && delta.getResource().isDerived();
+    }
+
+    private boolean isAboutTemplateChange(final IResourceDelta delta) {
+        return delta.getResource().getType() == IResource.FILE && delta.getKind() == IResourceDelta.CHANGED && isTemplate(delta);
+    }
+
+    private boolean isTemplate(final IResourceDelta delta) {
+        if (delta.getFullPath() != null) {
+            IFile file = FileProvider.findFile(delta.getFullPath());
+            return "mt".equals(file.getFileExtension());
+        }
+        return false;
+    }
+
+    /**
+     * Re-Initialize the interpreters for the Sessions
+     * 
+     * @param delta
+     */
+    private void processDelta(final IResourceDelta delta) {
+        interpreter.reconsiderTemplateFiles();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/CustomSystemServicesFactory.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/CustomSystemServicesFactory.java
new file mode 100644
index 0000000..e45fa27
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/CustomSystemServicesFactory.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalJavaService;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.ContextServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.PropertiesServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.RequestServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.ResourceServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.StringServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.SystemServicesFactory;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.XpathServices;
+
+/**
+ * Class used to customize the Acceleo internal systems.
+ * 
+ * @author cbrun
+ * 
+ */
+public class CustomSystemServicesFactory extends SystemServicesFactory {
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void addImports(final IScript script, final boolean isRoot) {
+        if (isRoot) {
+            script.addImport(new EvalJavaService(new StringServices(), false));
+            script.addImport(new EvalJavaService(new EObjectServices(), false));
+            script.addImport(new EvalJavaService(new XpathServices(), false));
+            script.addImport(new EvalJavaService(new ResourceServices(), false));
+            script.addImport(new EvalJavaService(new ContextServices(), false));
+        }
+        script.addImport(new EvalJavaService(new ENodeServices(script), true));
+        script.addImport(new EvalJavaService(new RequestServices(script), true));
+        if (script instanceof SpecificScript) {
+            script.addImport(new EvalJavaService(new PropertiesServices((SpecificScript) script), true));
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/ENodeHelper.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/ENodeHelper.java
new file mode 100644
index 0000000..90d413d
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/ENodeHelper.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException;
+import org.eclipse.sirius.common.tools.api.util.StringUtil;
+import org.eclipse.sirius.query.legacy.AcceleoInterpreterPlugin;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateElement;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+
+/**
+ * Utility class to handle ENodes.
+ * 
+ * @author cbrun
+ * 
+ */
+public final class ENodeHelper {
+    /**
+     * Utility class: no instantiation
+     */
+    private ENodeHelper() {
+    }
+
+    /**
+     * Transform the given {@link ENode} to a list of EObject. All elements not
+     * being {@link EObject} in the result will be ignored.
+     * 
+     * @param enode
+     *            any ENode.
+     * @return a list of {@link EObject}.
+     */
+    @SuppressWarnings("unchecked")
+    public static Collection<EObject> getAsListOfEObjects(final ENode enode) {
+        Collection<EObject> result = null;
+        try {
+            result = (Collection<EObject>) enode.getAdapterValue(Collection.class);
+        } catch (final ENodeCastException e) {
+            // silent catch
+        }
+        if (result != null) {
+            final Iterator<?> it = result.iterator();
+            while (it.hasNext()) {
+                final Object cur = it.next();
+                if (!(cur instanceof EObject)) {
+                    it.remove();
+                }
+            }
+        } else {
+            result = new ArrayList<EObject>();
+        }
+        return result;
+    }
+
+    /**
+     * Convert an {@link ENode} instance.
+     * 
+     * @param node
+     *            the {@link ENode} instance to convert
+     * @param s
+     *            the error message in case of {@link ENodeCastException}
+     * @return the converted object or null.
+     */
+    public static Object getValue(final ENode node, final String s) {
+        Object value = null;
+        if (!node.isNull()) {
+            try {
+                if (node.isEObject()) {
+                    value = node.getEObject();
+                } else if (node.isString()) {
+                    value = node.getString();
+                } else if (node.isBoolean()) {
+                    value = Boolean.valueOf(node.getBoolean());
+                } else if (node.isDouble()) {
+                    value = new Double(node.getDouble());
+                } else if (node.isInt()) {
+                    value = Integer.valueOf(node.getInt());
+                } else if (node.isList() && node.getList().size() > 0) {
+                    // FIXME specification for list in SetValue.
+                    value = node.getList().asList();
+                }
+            } catch (final ENodeCastException e) {
+                AcceleoInterpreterPlugin.getDefault().error(s, e);
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Wrapper method to evaluate an expression.
+     * 
+     * @param interpreter
+     *            an expression interpreter.
+     * @param target
+     *            the EObject instance to evaluate on.
+     * @param expression
+     *            the expression to evaluate.
+     * @return an ENode with the evaluation result.
+     * @throws EvaluationException
+     *             if the evaluation was not successful.
+     */
+    public static ENode evaluate(final AcceleoInterpreter interpreter, final EObject target, final String expression) throws EvaluationException {
+        ENode result = new ENode(null, (TemplateElement) null, true);
+        try {
+            if (!StringUtil.isEmpty(expression)) {
+                result = interpreter.evaluateENode(target, expression);
+            }
+
+        } catch (final EvaluationException e) {
+            throw new EvaluationException(e);
+        }
+        return result;
+    }
+
+    /**
+     * adapt an ENode to a boolean.
+     * 
+     * @param evaluate
+     *            ENode to adapt.
+     * @return the boolean value, false if adaptation fails.
+     */
+    public static boolean getAsBoolean(final ENode evaluate) {
+        boolean adaptedBool = false;
+        try {
+            if (evaluate.isBoolean()) {
+                return evaluate.getBoolean();
+            }
+            final Boolean value = (Boolean) evaluate.getAdapterValue(Boolean.class);
+            if (value != null) {
+                adaptedBool = value.booleanValue();
+            }
+        } catch (final ENodeCastException e) {
+            // silent catch
+        }
+        return adaptedBool;
+    }
+
+    /**
+     * adapt an ENode to an EObject.
+     * 
+     * @param result
+     *            ENode to adapt.
+     * @return the EObject value, null if no adaptation is possible.
+     */
+    public static EObject getAsEObject(final ENode result) {
+        EObject adaptedEObject = null;
+        try {
+            if (result.isEObject()) {
+                return result.getEObject();
+            } else {
+                adaptedEObject = (EObject) result.getAdapterValue(EObject.class);
+            }
+        } catch (final ENodeCastException e) {
+            // silent catch
+        }
+        return adaptedEObject;
+    }
+
+    /**
+     * adapt an ENode to an String.
+     * 
+     * @param result
+     *            ENode to adapt.
+     * @return the String value, null if no adaptation is possible.
+     */
+    public static String getAsString(final ENode result) {
+        String adaptedEObject = null;
+        try {
+            if (result.isString()) {
+                return result.getString();
+            } else {
+                adaptedEObject = (String) result.getAdapterValue(String.class);
+            }
+        } catch (final ENodeCastException e) {
+            // silent catch
+        }
+        return adaptedEObject;
+    }
+
+    /**
+     * adapt an ENode to an Integer.
+     * 
+     * @param result
+     *            ENode to adapt.
+     * @return the Integer value, null if no adaptation is possible.
+     */
+    public static Integer getAsInteger(final ENode result) {
+        Integer adaptedEObject = null;
+        try {
+            if (result.isInt()) {
+                return result.getInt();
+            } else {
+                adaptedEObject = (Integer) result.getAdapterValue(int.class);
+            }
+        } catch (final ENodeCastException e) {
+            // silent catch
+        }
+        return adaptedEObject;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/ENodeServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/ENodeServices.java
new file mode 100644
index 0000000..39c8d0e
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/ENodeServices.java
@@ -0,0 +1,770 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.sirius.query.legacy.ecore.factories.EFactory;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.format.Conventions;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+// CHECKSTYLE:OFF
+/**
+ * System services for ENode elements.
+ * 
+ * @author www.obeo.fr
+ * 
+ */
+public class ENodeServices {
+
+    /**
+     * The script.
+     */
+    protected IScript script;
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public ENodeServices(IScript script) {
+        this.script = script;
+    }
+
+    /**
+     * Gets all the nodes whose type is the given type.
+     * <p>
+     * An element is kept only if it's an EObject whose type is the given type
+     * or if it isn't an EObject.
+     * <p>
+     * Sample :
+     * <p>
+     * <li>a is an instance of class A</li>
+     * <li>b is an instance of class B</li>
+     * <li>c is an instance of class C</li>
+     * <li>B extends A</li>
+     * <p>
+     * If type equals "A" and node is a list {a, "\n", b, c}
+     * <p>
+     * the result is a list {a, "\n", b}.
+     * 
+     * @param node
+     *            is the list
+     * @param type
+     *            is the type kept
+     * @return a list that contains the nodes whose type is the given type.
+     * @throws ENodeCastException
+     *             if the given node isn't a list
+     * @throws FactoryException
+     */
+    public ENode filter(ENode node, String type) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList res = new ENodeList();
+            ENodeIterator it = node.getList().iterator();
+            while (it.hasNext()) {
+                ENode child = filter(it.next(), type);
+                if (!child.isNull()) {
+                    res.add(child);
+                }
+            }
+            return new ENode(res, node);
+        } else if (node.isEObject()) {
+            if (EFactory.eInstanceOf(node.getEObject(), type)) {
+                return node;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Gets all the nodes whose type is the given type.
+     * <p>
+     * An element is kept only if it's an EObject whose type is the given type
+     * or if it isn't an EObject.
+     * <p>
+     * Sample :
+     * <p>
+     * <li>a is an instance of class A</li>
+     * <li>b is an instance of class B</li>
+     * <li>c is an instance of class C</li>
+     * <li>B extends A</li>
+     * <p>
+     * If type equals "A" and node is a list {a, "\n", b, c}
+     * <p>
+     * the result is a list {a, "\n", b}.
+     * 
+     * @param node
+     *            is the list
+     * @param type
+     *            is the type kept
+     * @return a list that contains the nodes whose type is the given type.
+     * @throws ENodeCastException
+     *             if the given node isn't a list
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode cast(ENode node, String type) throws ENodeCastException, FactoryException {
+        return filter(node, type);
+    }
+
+    /**
+     * Add a separator between each element of the list. It returns the given
+     * node if it isn't a list.
+     * <p>
+     * Sample :
+     * <p>
+     * If separator equals "\t" and node is a list {a, b, c} the result is a
+     * list {a, "\t", b, "\t", c}.
+     * 
+     * @param node
+     *            is the list
+     * @param separator
+     *            is the separator
+     * @return a list that contains a separator between each element.
+     * @throws FactoryException
+     */
+    public ENode sep(ENode node, String separator) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENodeList res = new ENodeList();
+            ENodeIterator it = list.iterator();
+            if (it.hasNext()) {
+                ENode element = it.next();
+                boolean needSeparator = element.size() > 0;
+                res.add(element);
+                while (it.hasNext()) {
+                    element = it.next();
+                    if (needSeparator && element.size() > 0) {
+                        res.add(new ENode(separator, node));
+                        needSeparator = true;
+                    } else if (!needSeparator) {
+                        needSeparator = element.size() > 0;
+                    }
+                    res.add(element);
+                }
+            }
+            return new ENode(res, node);
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Add a separator between each element of the list and serialize the list.
+     * It returns node.toString() if it isn't a list.
+     * <p>
+     * Sample :
+     * <p>
+     * If separator equals "\t" and node is a list {a, b, c} the result is a
+     * string : a + "\t" + b + "\t" + c.
+     * 
+     * @param node
+     *            is the list
+     * @param separator
+     *            is the separator
+     * @return a string that contains a separator between each element.
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode sepStr(ENode node, String separator) throws ENodeCastException, FactoryException {
+        ENode result = sep(node, separator);
+        result.asString();
+        return result;
+    }
+
+    /**
+     * Get recursively the feature value of an object. The recursivity is
+     * stopped when an element of the given type is found.
+     * <p>
+     * The given node must be an EObject.
+     * <p>
+     * Sample :
+     * <p>
+     * <li>a is an instance of class A</li>
+     * <li>b is an instance of class B</li>
+     * <li>c is an instance of class C</li>
+     * <li>a contains b</li>
+     * <li>b contains c</li>
+     * <li>'container' feature is defined on a, b, and c</li>
+     * <li>c.container returns b</li>
+     * <li>b.container returns a</li>
+     * <li>a.container returns null</li>
+     * <p>
+     * until(c,"container","A") returns a
+     * <p>
+     * until(b,"container","A") returns a
+     * <p>
+     * until(a,"container","A") returns a
+     * <p>
+     * until(b,"container","C") returns null
+     * <p>
+     * 
+     * @param node
+     *            is an EObject
+     * @param link
+     *            is the feature name
+     * @param type
+     *            is the type which stops the recursivity
+     * @return the found object or null
+     * @throws ENodeCastException
+     *             if the given node isn't an EObject
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode until(ENode node, String link, String type) throws ENodeCastException, FactoryException {
+        EObject object = node.getEObject();
+        while (object != null) {
+            if (EFactory.eInstanceOf(object, type)) {
+                return new ENode(object, node);
+            } else {
+                object = EFactory.eGetAsEObject(object, link);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the current node
+     */
+    public ENode current(ENode node) {
+        return node;
+    }
+
+    /**
+     * Returns the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @param level
+     *            is the level in the parent hierarchy
+     * @return the current node
+     * @throws ENodeCastException
+     */
+    public ENode current(ENode node, ENode arg) throws ENodeCastException {
+        if (arg.isString()) {
+            String type = arg.getString();
+            int i = 0;
+            Object value = script.contextAt(IScript.TEMPLATE_NODE, i);
+            while (value != null) {
+                ENode current = ENode.createTry(value, node);
+                if (current != null && current.isEObject()) {
+                    if (EFactory.eInstanceOf(current.getEObject(), type)) {
+                        return current;
+                    }
+                }
+                i++;
+                value = script.contextAt(IScript.TEMPLATE_NODE, i);
+            }
+        } else if (arg.isInt()) {
+            Object value = script.contextAt(IScript.TEMPLATE_NODE, arg.getInt());
+            return ENode.createTry(value, node);
+        }
+        return new ENode(ENode.EMPTY, node);
+    }
+
+    /**
+     * Transforms the node into a string.
+     * 
+     * @param node
+     *            is the current node
+     * @return the string node
+     */
+    public ENode toString(ENode node) {
+        node.asString();
+        return node;
+    }
+
+    /**
+     * Returns the adaptive value for the given type short name.
+     * 
+     * @param node
+     *            is the node
+     * @param type
+     *            is the type name : "EObject", "ENodeList", "String",
+     *            "boolean", "int", "double", "List", "ENode"
+     * @return the adaptive value
+     * @throws ENodeCastException
+     */
+    public ENode adapt(ENode node, String type) throws ENodeCastException {
+        Class<?> c;
+        if ("EObject".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = EObject.class;
+        } else if ("ENodeList".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = ENodeList.class;
+        } else if ("String".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = String.class;
+        } else if ("boolean".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = boolean.class;
+        } else if ("int".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = int.class;
+        } else if ("double".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = double.class;
+        } else if ("List".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = List.class;
+        } else if ("ENode".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = ENode.class;
+        } else {
+            c = null;
+        }
+        ENode result = ENode.createTry(node.getAdapterValue(c), node);
+        if (result != null) {
+            return result;
+        } else {
+            return new ENode(ENode.EMPTY, node);
+        }
+    }
+
+    /**
+     * It prints current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the current node
+     */
+    public ENode debug(ENode node) {
+        return trace(node);
+    }
+
+    /**
+     * It prints current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the current node
+     */
+    public ENode trace(ENode node) {
+        return trace(node, ""); //$NON-NLS-1$
+    }
+
+    /**
+     * It prints current node.
+     * 
+     * @param node
+     *            is the current node
+     * @param template
+     *            is the template to evaluate for each node
+     * @return the current node
+     */
+    public ENode trace(ENode node, String template) {
+        trace++;
+        String prefix;
+        if (template != null && template.length() > 0) {
+            try {
+                prefix = Conventions.formatString(template) + '=' + Conventions.formatString(evaluate(node, template).toString());
+            } catch (TemplateSyntaxException e) {
+                prefix = ""; //$NON-NLS-1$
+            } catch (FactoryException e) {
+                prefix = ""; //$NON-NLS-1$
+            }
+        } else {
+            prefix = ""; //$NON-NLS-1$
+        }
+        String marker = ('[' + trace + "]          ").substring(0, 10); //$NON-NLS-1$
+        System.out.println(marker + prefix + ' ' + AcceleoGenMessages.getString("ENodeServices.TraceMessage", new Object[] { node.getType(), Conventions.formatString(node.toString()), })); //$NON-NLS-1$
+        return node;
+    }
+
+    private int trace = 0;
+
+    private ENode evaluate(ENode current, String call) throws TemplateSyntaxException, FactoryException {
+        int pos = getBegin();
+        call = call.replaceAll("'", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateExpression expression = TemplateExpression.fromString(computeCall(pos, call), new Int2(pos, pos + call.length()), script);
+        try {
+            return expression.evaluate(current, script, LaunchManager.create("run", true)); //$NON-NLS-1$
+        } catch (ENodeException e) {
+            return new ENode(ENode.EMPTY, current);
+        }
+    }
+
+    private int getBegin() {
+        Int2 pos = (Int2) script.contextPeek(IScript.ARGUMENT_POSITION);
+        if (pos != null) {
+            return pos.b();
+        } else {
+            return 0;
+        }
+    }
+
+    private String computeCall(int begin, String call) {
+        if (begin > 0) {
+            StringBuffer result = new StringBuffer(""); //$NON-NLS-1$
+            for (int i = 0; i < begin; i++) {
+                result.append(' ');
+            }
+            result.append(call);
+            return result.toString();
+        } else {
+            return call;
+        }
+    }
+
+    /***************************************************************************
+     * 
+     * List Services
+     * 
+     **************************************************************************/
+
+    /**
+     * Returns the size of the node.
+     * 
+     * @param node
+     *            is the current node <li>isEObject() : return 1</li> <li>
+     *            isList() : return getList().size()</li> <li>isString() :
+     *            return getString().length()</li> <li>isBoolean() : return 1</li>
+     *            <li>isInt() : return 1</li> <li>isNull() : return 0</li>
+     * @return value size
+     */
+    public int nSize(ENode node) {
+        return node.size();
+    }
+
+    /**
+     * Returns the child node at the given index in the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @param index
+     *            is the index of the child
+     * @return the child node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nGet(ENode node, int index) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENode result = list.get(index);
+            if (result != null) {
+                return result;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else if (index == 0) {
+            return node;
+        } else {
+            return new ENode(ENode.EMPTY, node);
+        }
+    }
+
+    /**
+     * Returns the children in the given range.
+     * 
+     * @param node
+     *            is the current node
+     * @param begin
+     *            is the beginning index
+     * @param begin
+     *            is the ending index
+     * @return the children in the given range
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nGet(ENode node, int begin, int end) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENodeList result = new ENodeList();
+            for (int i = begin; i < list.size() && (i < end || end == -1); i++) {
+                ENode child = list.get(i);
+                result.add(child);
+            }
+            return new ENode(result, node);
+        } else if (begin == 0 && (end > 0 || end == -1)) {
+            return node;
+        } else {
+            return new ENode(ENode.EMPTY, node);
+        }
+    }
+
+    /**
+     * Returns the first child of the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the first child node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nFirst(ENode node) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENode result = list.get(0);
+            if (result != null) {
+                return result;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Returns the last child of the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the last child node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nLast(ENode node) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENode result = list.get(list.size() - 1);
+            if (result != null) {
+                return result;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Removes all duplicated nodes.
+     * 
+     * @param node
+     *            is the current node
+     * @return the minimized node
+     * @throws ENodeCastException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode minimize(ENode node) throws ENodeCastException {
+        return nMinimize(node);
+    }
+
+    /**
+     * Removes all duplicated nodes.
+     * 
+     * @param node
+     *            is the current node
+     * @return the minimized node
+     * @throws ENodeCastException
+     */
+    public ENode nMinimize(ENode node) throws ENodeCastException {
+        if (node.isList()) {
+            ENodeList result = new ENodeList(true);
+            result.addAll(node.getList());
+            return new ENode(result, node);
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Reverses the order of the elements of the specified node.
+     * 
+     * @param node
+     *            is the node whose elements are to be reversed
+     * @return the new node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode reverse(ENode node) throws ENodeCastException, FactoryException {
+        return nReverse(node);
+    }
+
+    /**
+     * Reverses the order of the elements of the specified node.
+     * 
+     * @param node
+     *            is the node whose elements are to be reversed
+     * @return the new node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nReverse(ENode node) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList result = new ENodeList();
+            ENodeIterator it = node.getList().iterator();
+            while (it.hasNext()) {
+                ENode child = it.next();
+                if (!child.isNull()) {
+                    result.add(0, child);
+                }
+            }
+            return new ENode(result, node);
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Returns true if this list contains the specified element.
+     * <p>
+     * More formally, returns true if and only if this list contains at least
+     * <p>
+     * one element e such that (o==null ? e==null : o.equals(e)).
+     * 
+     * @param node
+     *            is the current node
+     * @param element
+     *            is element whose presence in this list is to be tested
+     * @return true if this list contains the specified element
+     * @throws ENodeCastException
+     */
+    public boolean nContains(ENode node, ENode element) throws ENodeCastException {
+        if (node.isList()) {
+            return node.getList().contains(element);
+        } else {
+            return node.equals(element);
+        }
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param node
+     *            is the current node
+     * @return the sorted node
+     * @throws ENodeCastException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode sort(ENode node) throws ENodeCastException {
+        return nMinimize(nSort(node));
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param node
+     *            is the current node
+     * @return the sorted node
+     * @throws ENodeCastException
+     */
+    public ENode nSort(ENode node) throws ENodeCastException {
+        if (node.isList()) {
+            node.getList().sort();
+        }
+        return node;
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to evaluate for each node
+     * @return the sorted node
+     * @throws ENodeCastException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode sort(ENode current, String call) throws ENodeCastException {
+        return nMinimize(nSort(current, call));
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to evaluate for each node
+     * @return the sorted node
+     * @throws ENodeCastException
+     */
+    public ENode nSort(ENode current, String call) throws ENodeCastException {
+        if (!current.isList()) {
+            return current;
+        } else {
+            // Optimization #1: compile the expression only once.
+            TemplateExpression expr = compileExpression(call);
+            if (expr == null) {
+                return current;
+            }
+            // Optimization #2: compute the sort keys only once for each
+            // element.
+            ENode[][] elementsWithSortKeys = attachSortKeys(current.getList(), expr);
+            Arrays.sort(elementsWithSortKeys, new Comparator<ENode[]>() {
+                public int compare(ENode[] pair1, ENode[] pair2) {
+                    ENode key1 = pair1[1];
+                    ENode key2 = pair2[1];
+                    return key1.compareTo(key2);
+                }
+            });
+            ENodeList result = new ENodeList();
+            for (ENode[] elementsWithSortKey : elementsWithSortKeys) {
+                result.add(elementsWithSortKey[0]);
+            }
+            return new ENode(result, current);
+        }
+    }
+
+    /**
+     * Build a 2-dimensional array of ENode. Each element of the array is a pair
+     * where the first element is the original ENode and the second is the sort
+     * key, i.e. the result of evaluating the sort expression on that node.
+     */
+    private ENode[][] attachSortKeys(ENodeList elements, TemplateExpression expr) throws ENodeCastException {
+        ENode[][] elementsWithSortKeys = new ENode[elements.size()][2];
+        for (int i = 0; i < elementsWithSortKeys.length; i++) {
+            ENode element = elements.get(i);
+            ENode sortKey = evaluate(element, expr);
+            elementsWithSortKeys[i] = new ENode[] { element, sortKey };
+        }
+        return elementsWithSortKeys;
+    }
+
+    private TemplateExpression compileExpression(String call) {
+        int pos = getBegin();
+        call = call.replaceAll("'", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$
+        try {
+            return TemplateExpression.fromString(computeCall(pos, call), new Int2(pos, pos + call.length()), script);
+        } catch (TemplateSyntaxException e) {
+            return null;
+        }
+    }
+
+    private ENode evaluate(ENode current, TemplateExpression expr) {
+        try {
+            return expr.evaluate(current, script, LaunchManager.create("run", true)); //$NON-NLS-1$
+        } catch (ENodeException e) {
+            return new ENode(ENode.EMPTY, current);
+        } catch (FactoryException e) {
+            return new ENode(ENode.EMPTY, current);
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/EObjectServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/EObjectServices.java
new file mode 100644
index 0000000..8951b84
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/EObjectServices.java
@@ -0,0 +1,381 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.sirius.query.legacy.ecore.factories.EFactory;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.tools.resources.FileContentMap;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+
+/**
+ * This class comes from Acceleo, it provides the basic browsing services :
+ * eContainer(), eAllContents().... It is needed here for two things : handle
+ * metamodel extensions, and fix issues with cache on eAllContents().
+ * 
+ * @author cbrun
+ * 
+ */
+public class EObjectServices {
+    private FileContentMap load = new FileContentMap();
+
+    private EPackage eRootPackage;
+
+    private Map<String, List<String>> eClass2containments = new HashMap<String, List<String>>();
+
+    private Map<EClass, List<EClass>> eClass2subTypes;
+
+    /**
+     * Gets the container of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the container
+     */
+    public EObject eContainer(final EObject current) {
+        return current.eContainer();
+    }
+
+    /**
+     * Gets recursively the container of an EObject. The recursion is stopped
+     * when an element of the given type is found.
+     * 
+     * @param root
+     *            : current instance.
+     * @param type
+     *            : type name.
+     * @return the parent.
+     * @throws FactoryException
+     *             on type error.
+     */
+    public EObject eContainer(final EObject root, final String type) throws FactoryException {
+        EObject current = root;
+        while (current != null) {
+            if (EFactory.eInstanceOf(current, type)) {
+                return current;
+            } else {
+                current = current.eContainer();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the root container; it may be this object itself and it will have
+     * a <code>null</code> {@link EObject#eContainer container}.
+     * <p>
+     * The root container must be {@link Resource#getContents directly
+     * contained} in a resource for its {@link EObject#eAllContents tree} to be
+     * {@link Resource#save(java.util.Map) serializable}.
+     * </p>
+     * 
+     * @param eObject
+     *            the object to get the root container for.
+     * @return the root container.
+     */
+    public EObject getRootContainer(final EObject eObject) {
+        return EcoreUtil.getRootContainer(eObject);
+    }
+
+    /**
+     * Gets the metamodel class of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the metamodel class
+     */
+    public EObject eClass(final EObject current) {
+        return current.eClass();
+    }
+
+    /**
+     * Gets the children of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the children
+     */
+    public EList<EObject> eContents(final EObject current) {
+        return current.eContents();
+    }
+
+    /**
+     * Gets all the direct contents and indirect contents of this object.
+     * 
+     * @param current
+     *            is the object
+     * @return the contents
+     */
+    public ENodeList eAllContents(final ENode current) {
+        final ENodeList result = new ENodeList();
+        try {
+            if (current.isList()) {
+                final ENodeIterator it = current.getList().iterator();
+                while (it.hasNext()) {
+                    result.addAll(eAllContents(it.next()));
+                }
+            } else if (current.isEObject()) {
+                final TreeIterator<EObject> it = current.getEObject().eAllContents();
+                while (it.hasNext()) {
+                    result.add(ENode.createTry(it.next(), current));
+                }
+            }
+        } catch (final ENodeCastException e) {
+            // Never catch
+        }
+        return result;
+    }
+
+    /**
+     * Gets all the direct contents and indirect contents of the object.
+     * 
+     * @param current
+     *            is the object
+     * @param type
+     *            is the type of the objects to select
+     * @return the contents
+     * @throws FactoryException
+     *             on type error.
+     */
+    public ENodeList eAllContents(final ENode current, final String type) throws FactoryException {
+        final ENodeList result = new ENodeList();
+        try {
+            if (current.isList()) {
+                final ENodeIterator it = current.getList().iterator();
+                while (it.hasNext()) {
+                    result.addAll(eAllContents(it.next(), type));
+                }
+            } else if (current.isEObject()) {
+                final int i = type.lastIndexOf(".");
+                final String typeName = i > -1 ? type.substring(i + 1) : type;
+                final List<EObject> children = eAllContents(current.getEObject(), type, typeName);
+                final Iterator<EObject> it = children.iterator();
+                while (it.hasNext()) {
+                    result.add(ENode.createTry(it.next(), current));
+                }
+            }
+        } catch (final ENodeCastException e) {
+            // Never catch
+        }
+        return result;
+    }
+
+    private List<EObject> eAllContents(final EObject object, final String type, final String typeName) {
+        final List<EObject> result = new ArrayList<EObject>();
+        final List<String> containmentTypeNames = getContainmentNames(object);
+        if (containmentTypeNames.contains(typeName)) {
+            final Iterator<EObject> eContents = object.eContents().iterator();
+            while (eContents.hasNext()) {
+                final EObject eContent = eContents.next();
+                if (EFactory.eInstanceOf(eContent, type)) {
+                    result.add(eContent);
+                }
+                result.addAll(eAllContents(eContent, type, typeName));
+            }
+        }
+        return result;
+    }
+
+    private List<String> getContainmentNames(final EObject object) {
+        final EClass eClass = object.eClass();
+        final EPackage ePackage = (EPackage) getRootContainer(eClass);
+        if (ePackage != eRootPackage) {
+            eRootPackage = ePackage;
+            eClass2containments.clear();
+            eClass2subTypes = null;
+        }
+        final String eClassName = eClass.getName();
+        List<String> containmentNames = eClass2containments.get(eClassName);
+        if (containmentNames == null) {
+            containmentNames = new ArrayList<String>();
+            computeContainments(new ArrayList<EClassifier>(), containmentNames, ePackage, eClass.getEAllReferences());
+            eClass2containments.put(eClassName, containmentNames);
+        }
+        return containmentNames;
+    }
+
+    private void computeContainments(final List<EClassifier> containmentTypes, final List<String> containmentNames, final EPackage ePackage, final Iterable<EReference> eReferences) {
+        final Iterator<EReference> references = eReferences.iterator();
+        while (references.hasNext()) {
+            final EReference eReference = references.next();
+            if (eReference.isContainment()) {
+                final List<EClassifier> types = new ArrayList<EClassifier>();
+                types.add(eReference.getEType());
+                if (eReference.getEType() instanceof EClass) {
+                    types.addAll(((EClass) eReference.getEType()).getEAllSuperTypes());
+                }
+                types.addAll(eClass2subTypes(ePackage, eReference.getEType()));
+                final Iterator<EClassifier> it = types.iterator();
+                while (it.hasNext()) {
+                    final EClassifier type = it.next();
+                    if (type instanceof EClass) {
+                        final String name = type.getName();
+                        if (!containmentTypes.contains(type)) {
+                            containmentTypes.add(type);
+                            containmentNames.add(name);
+                            computeContainments(containmentTypes, containmentNames, ePackage, getEReferences((EClass) type));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private Iterable<EReference> getEReferences(final EClass type) {
+        return Iterables.filter(type.getEStructuralFeatures(), EReference.class);
+    }
+
+    private List<EClass> eClass2subTypes(final EPackage ePackage, final EClassifier eClass) {
+        if (eClass2subTypes == null) {
+            eClass2subTypes = Maps.newHashMap();
+            final Iterator<?> classifiers = ETools.computeAllClassifiersList(ePackage, false).iterator();
+            while (classifiers.hasNext()) {
+                final Object next = classifiers.next();
+                if (next instanceof EClass) {
+                    final EClass c = (EClass) next;
+                    final Iterator<EClass> superTypes = c.getEAllSuperTypes().iterator();
+                    while (superTypes.hasNext()) {
+                        final EClass superType = superTypes.next();
+                        List<EClass> subTypes = eClass2subTypes.get(superType);
+                        if (subTypes == null) {
+                            subTypes = new ArrayList<EClass>();
+                            eClass2subTypes.put(superType, subTypes);
+                        }
+                        if (!subTypes.contains(c)) {
+                            subTypes.add(c);
+                        }
+                    }
+                }
+            }
+        }
+        List<EClass> types = eClass2subTypes.get(eClass);
+        if (types == null) {
+            types = new ArrayList<EClass>();
+        }
+        return types;
+    }
+
+    /**
+     * Gets the containing feature of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the containing feature
+     */
+    public EStructuralFeature eContainingFeature(final EObject current) {
+        return current.eContainingFeature();
+    }
+
+    /**
+     * Gets the containment feature of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the containment feature
+     */
+    public EReference eContainmentFeature(final EObject current) {
+        return current.eContainmentFeature();
+    }
+
+    /**
+     * Gets the cross referenced objects.
+     * 
+     * @param current
+     *            is the object
+     * @return the cross referenced objects
+     */
+    public List<EObject> eCrossReferences(final EObject current) {
+        return current.eCrossReferences();
+    }
+
+    /**
+     * Gets the containing resource, or null.
+     * 
+     * @param current
+     *            is the object
+     * @return the resource
+     */
+    public String eResource(final EObject current) {
+        if (current != null && current.eResource() != null) {
+            return current.eResource().getURI().path();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the containing resource name, or null.
+     * 
+     * @param current
+     *            is the object
+     * @return the resource
+     */
+    public String eResourceName(final EObject current) {
+        if (current != null && current.eResource() != null) {
+            return current.eResource().getURI().lastSegment();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Loads the root element of the given model.
+     * 
+     * @param node
+     *            is the current node
+     * @param rootpath
+     *            is the path of the model to load
+     * @return the root element of the model
+     */
+    public EObject load(final ENode node, final String rootpath) {
+        String path = rootpath;
+        if (path.startsWith("/resource")) {
+            path = path.substring("/resource".length());
+        }
+        final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
+        if (file.exists()) {
+            EObject result = (EObject) load.get(file);
+            if (result == null) {
+                result = ETools.loadXMI(path);
+                load.put(file, result);
+            }
+            return result;
+        } else {
+            return ETools.loadXMI(path);
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/IAcceleoInterpreterMessages.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/IAcceleoInterpreterMessages.java
new file mode 100644
index 0000000..44986dc
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/IAcceleoInterpreterMessages.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+/**
+ * Messages for the acceleo interpreter.
+ * 
+ * @author ymortier
+ */
+public interface IAcceleoInterpreterMessages {
+
+    /** Error while evaluating Acceleo Expression. */
+    String EVALUATION_ERROR = "Error while evaluating Acceleo expression";
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/SmartSpecificScript.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/SmartSpecificScript.java
new file mode 100644
index 0000000..0265b26
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/business/internal/interpreter/SmartSpecificScript.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008, 2009 THALES GLOBAL SERVICES.
+ * 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.business.internal.interpreter;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
+import org.eclipse.sirius.ecore.extender.business.api.accessor.exception.FeatureNotFoundException;
+import org.eclipse.sirius.query.legacy.AcceleoInterpreterPlugin;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxExceptions;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalJavaService;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.JavaServiceNotFoundException;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.SystemServicesFactory;
+
+/**
+ * A {@link SpecificScript} subcall optimized for performance and which support
+ * metamodel extensions.
+ * 
+ * @author mchauvin
+ */
+public class SmartSpecificScript extends SpecificScript {
+    /**
+     * Keyword used for the inverse references of an element.
+     */
+    protected static final String INVERSE_KEYWORD = "\u007E";
+
+    private final AcceleoExtendedInterpreter interpreter;
+
+    private ECrossReferenceAdapter crossReferencer;
+
+    private final List<File> representationDescriptionFiles;
+
+    /**
+     * Constructor.
+     * 
+     * @param file
+     *            is the script file that contains the specific configuration
+     * @param interpreter
+     *            is the acceleo interpreter to use
+     */
+    public SmartSpecificScript(final File file, final AcceleoExtendedInterpreter interpreter) {
+        super(file);
+        this.interpreter = interpreter;
+        representationDescriptionFiles = new ArrayList<File>();
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param moreSpecificRepresentationDescriptionFile
+     *            the more specific representation description file
+     * @param representationDescriptionFiles
+     *            is the list of files to use as Acceleo template
+     * @param interpreter
+     *            is the acceleo interpreter to use
+     */
+    public SmartSpecificScript(final File moreSpecificRepresentationDescriptionFile, final List<File> representationDescriptionFiles, final AcceleoExtendedInterpreter interpreter) {
+        super(moreSpecificRepresentationDescriptionFile);
+        this.interpreter = interpreter;
+        this.representationDescriptionFiles = representationDescriptionFiles;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.gen.template.scripts.AbstractScript#createSystemServicesFactory()
+     */
+    @Override
+    protected SystemServicesFactory createSystemServicesFactory() {
+        return new CustomSystemServicesFactory();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.gen.template.scripts.AbstractScript#eGet(org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression,
+     *      org.eclipse.sirius.query.legacy.gen.template.eval.ENode,
+     *      org.eclipse.sirius.query.legacy.gen.template.eval.ENode[],
+     *      org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager, boolean)
+     */
+    @Override
+    public ENode eGet(final TemplateCallExpression call, final ENode node, final ENode[] args, final LaunchManager mode, final boolean recursiveSearch) throws FactoryException, ENodeException {
+        final String name = call.getLink();
+        ENode result = interpreter.getFromCache(node, name, args);
+        if (result == null) {
+            result = super.eGet(call, node, args, mode, recursiveSearch);
+            if (result != null) {
+                interpreter.cache(node, name, args, result);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript#eGetTemplate(org.eclipse.sirius.query.legacy.gen.template.eval.ENode,
+     *      java.lang.String, org.eclipse.sirius.query.legacy.gen.template.eval.ENode[],
+     *      org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager)
+     */
+    @Override
+    public ENode eGetTemplate(final ENode node, final String name, final ENode[] args, final LaunchManager mode) throws ENodeException, FactoryException {
+        ENode result = null;
+        if (name.startsWith(AcceleoInterpreter.VARIABLE_KEYWORD)) {
+            if (interpreter.isVariableSet(name.substring(1))) {
+                return interpreter.getVariableValue(name.substring(1));
+            }
+            throw new FactoryException("Variable " + name.substring(1) + " not found");
+        } else {
+            try {
+                if (name.startsWith(INVERSE_KEYWORD) && node.isEObject()) {
+                    result = getInverseReference(node, name);
+                }
+            } catch (final ENodeCastException e1) {
+                AcceleoInterpreterPlugin.getDefault().error("Error trying to resolve inverse references", e1);
+            }
+        }
+        /* Metamodel extension */
+        if (result == null && node.isEObject()) {
+            try {
+                final EObject cur = node.getEObject();
+                if (this.interpreter.accessor != null && this.interpreter.accessor.eValid(cur, name)) {
+                    final Object res = this.interpreter.accessor.eGet(cur, name);
+                    result = ENode.createTry(res, node);
+                }
+            } catch (final ENodeCastException e) {
+                AcceleoInterpreterPlugin.getDefault().error("Error trying to get metamodel extensions.", e);
+            } catch (final FeatureNotFoundException e) {
+                AcceleoInterpreterPlugin.getDefault().error("Error accessing metamodel extensions.", e);
+            }
+        }
+        if (result == null) {
+            result = super.eGetTemplate(node, name, args, mode);
+        }
+        return result;
+    }
+
+    private ENode getInverseReference(final ENode node, final String name) throws ENodeCastException {
+        ENode result = null;
+        if (crossReferencer != null) {
+            final Collection<EStructuralFeature.Setting> settings = crossReferencer.getInverseReferences(node.getEObject());
+            String inverseName = null;
+            if (name.length() > INVERSE_KEYWORD.length()) {
+                inverseName = name.substring(INVERSE_KEYWORD.length());
+            }
+            final Collection<EObject> referencing = new HashSet<EObject>(settings.size());
+            for (final EStructuralFeature.Setting setting : settings) {
+                if (inverseName == null) {
+                    referencing.add(setting.getEObject());
+                } else if (setting.getEStructuralFeature().getName().equals(inverseName)) {
+                    referencing.add(setting.getEObject());
+                }
+            }
+            result = ENode.createTry(referencing, node);
+        }
+        return result;
+    }
+
+    /**
+     * Set the cross referencer used to evaluate the "tilde" syntax.
+     * 
+     * @param referencer
+     *            referencer to use for evaluation.
+     */
+    public void setCrossReferencer(final ECrossReferenceAdapter referencer) {
+        this.crossReferencer = referencer;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript#reset()
+     */
+    @Override
+    public void reset() throws TemplateSyntaxExceptions {
+        super.reset();
+        /*
+         * we set the file as null as we don't want Acceleo to read it on every
+         * ENodeException.getMessage() or we'll loose performances for nothing!
+         */
+        file = null;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript#reset(java.lang.String)
+     */
+    @Override
+    public void reset(final String content) throws TemplateSyntaxExceptions {
+        super.reset(content);
+        /*
+         * we set the file as null as we don't want Acceleo to read it on every
+         * ENodeException.getMessage() or we'll loose performances for nothing!
+         */
+        file = null;
+    }
+
+    /**
+     * {@inheritDoc} <BR>
+     * Search in all representation description files if the import can be
+     * resolved.
+     * 
+     * @see org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript#resolveScriptFile(java.io.File,
+     *      java.lang.String, java.lang.String)
+     */
+    @Override
+    protected File resolveScriptFile(final File script, final String importValue, final String extension) {
+        File result = null;
+        for (File odesignFile : representationDescriptionFiles) {
+            result = super.resolveScriptFile(odesignFile, importValue, extension);
+            if (result != null) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}<BR>
+     * Search in all representation description files if the import can be
+     * resolved.
+     * 
+     * @see org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript#addImportForJavaService(java.io.File,
+     *      java.lang.String)
+     */
+    @Override
+    protected void addImportForJavaService(final File file, final String value) throws JavaServiceNotFoundException {
+        boolean javaServiceFound = false;
+        final StringBuffer errorMessage = new StringBuffer("");
+
+        for (File odesignFile : representationDescriptionFiles) {
+            try {
+                addImport(new EvalJavaService(odesignFile, value));
+                javaServiceFound = true;
+            } catch (final JavaServiceNotFoundException e) {
+                errorMessage.append(e.getMessage());
+                errorMessage.append("\n");
+            }
+            if (javaServiceFound) {
+                break;
+            }
+        }
+        if (!javaServiceFound) {
+            if (errorMessage.length() == 0) {
+                throw new JavaServiceNotFoundException("no representation description files found so " + value + "could not be de found");
+            } else {
+                throw new JavaServiceNotFoundException(errorMessage.substring(0, errorMessage.length() - 1));
+            }
+        }
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/AcceleoEcoreMessages.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/AcceleoEcoreMessages.java
new file mode 100644
index 0000000..9301916
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/AcceleoEcoreMessages.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.query.legacy.ecore;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class to access externalized Strings for Acceleo's ecore.
+ * 
+ */
+public final class AcceleoEcoreMessages {
+    /** Full qualified path to the properties file in which to seek the keys. */
+    private static final String BUNDLE_NAME = "org.eclipse.sirius.query.legacy.ecore.acceleoecoremessages"; //$NON-NLS-1$
+
+    /** Contains the locale specific {@link String}s needed by this plug-in. */
+    private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(AcceleoEcoreMessages.BUNDLE_NAME);
+
+    /**
+     * Utility classes don't need to (and shouldn't) be instantiated.
+     */
+    private AcceleoEcoreMessages() {
+        // prevents instantiation
+    }
+
+    /**
+     * Returns a specified {@link String} from the resource bundle.
+     * 
+     * @param key
+     *            Key of the String we seek.
+     * @return The String from the resource bundle associated with
+     *         <code>key</code>.
+     */
+    public static String getString(String key) {
+        try {
+            return AcceleoEcoreMessages.getString(key, new Object[] {});
+        } catch (MissingResourceException e) {
+            return '!' + key + '!';
+        }
+    }
+
+    /**
+     * Returns a String from the resource bundle binded with the given
+     * arguments.
+     * 
+     * @param key
+     *            Key of the String we seek.
+     * @param arguments
+     *            Arguments for the String formatting.
+     * @return formatted {@link String}.
+     * @see MessageFormat#format(String, Object[])
+     */
+    public static String getString(String key, Object[] arguments) {
+        if (arguments == null) {
+            return MessageFormat.format(AcceleoEcoreMessages.RESOURCE_BUNDLE.getString(key), new Object[] {});
+        }
+        return MessageFormat.format(AcceleoEcoreMessages.RESOURCE_BUNDLE.getString(key), arguments);
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/AcceleoEcorePlugin.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/AcceleoEcorePlugin.java
new file mode 100644
index 0000000..7b64301
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/AcceleoEcorePlugin.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.ecore;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.sirius.query.legacy.tools.resources.AcceleoPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ * 
+ * 
+ */
+public class AcceleoEcorePlugin extends AcceleoPlugin {
+
+    /* (non-Javadoc) */
+    @Override
+    public String getID() {
+        return "org.eclipse.sirius.query.legacy.ecore"; //$NON-NLS-1$
+    }
+
+    /**
+     * The shared instance.
+     */
+    private static AcceleoEcorePlugin plugin;
+
+    /**
+     * Resource bundle.
+     */
+    private ResourceBundle resourceBundle;
+
+    /**
+     * The constructor.
+     */
+    public AcceleoEcorePlugin() {
+        super();
+        AcceleoEcorePlugin.plugin = this;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public void start(BundleContext context) throws Exception {
+        super.start(context);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        super.stop(context);
+        AcceleoEcorePlugin.plugin = null;
+        resourceBundle = null;
+    }
+
+    /**
+     * @return the shared instance
+     */
+    public static AcceleoEcorePlugin getDefault() {
+        return AcceleoEcorePlugin.plugin;
+    }
+
+    /**
+     * Returns the string from the plugin's resource bundle, or 'key' if not
+     * found.
+     * 
+     * @param key
+     *            identifies the string
+     * @return the string from the plugin's resource bundle, or 'key' if not
+     *         found
+     */
+    public static String getResourceString(String key) {
+        ResourceBundle bundle = AcceleoEcorePlugin.getDefault().getResourceBundle();
+        try {
+            return (bundle != null) ? bundle.getString(key) : key;
+        } catch (MissingResourceException e) {
+            return key;
+        }
+    }
+
+    /**
+     * Returns the plugin's resource bundle.
+     * 
+     * @return the plugin's resource bundle
+     */
+    public ResourceBundle getResourceBundle() {
+        try {
+            if (resourceBundle == null) {
+                resourceBundle = ResourceBundle.getBundle("org.eclipse.sirius.query.legacy.ecore.AcceleoEcorePluginResources"); //$NON-NLS-1$
+            }
+        } catch (MissingResourceException x) {
+            resourceBundle = null;
+        }
+        return resourceBundle;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/acceleoecoremessages.properties b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/acceleoecoremessages.properties
new file mode 100644
index 0000000..fa02e5d
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/acceleoecoremessages.properties
@@ -0,0 +1,25 @@
+#===============================================================================
+# Copyright (c) 2005-2014 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:
+#    Obeo - initial API and implementation
+#===============================================================================
+## NOTE TO TRANSLATORS : apostrophes (') need to be doubled if you need one displayed
+## org.eclipse.sirius.query.legacy.ecore.factories
+# NOTE : "Factory" should not be translated.
+EFactory.UnexpectedException = Factory error : {0}
+EFactory.UnresolvedFactory = Factory not found : {0}
+EFactory.UnresolvedLink = The link "{0}" does not exist in class "{1}"
+
+Factories.UnresolvedFactoryId = Unresolved factory id={0}
+Factories.CreationFailed = Object {0} was not created
+
+## org.eclipse.sirius.query.legacy.ecore.tools
+ELoaderUtils.MetamodelConflict = Ecore metamodel conflict in project "{0}"
+ETools.ModelValidationNeeded = You have to validate the ecore {0}
+ETools.ModelValidationRecommended = The ecore {0} should be validated
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/factories/EFactory.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/factories/EFactory.java
new file mode 100644
index 0000000..2f534d1
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/factories/EFactory.java
@@ -0,0 +1,566 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.ecore.factories;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.Enumerator;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EEnum;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.sirius.query.legacy.ecore.AcceleoEcoreMessages;
+import org.eclipse.sirius.query.legacy.ecore.AcceleoEcorePlugin;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+
+/**
+ * This is a factory for an ecore metamodel. There is a factory by package. Each
+ * factory is used to create instances of classifiers.
+ * 
+ * 
+ */
+public class EFactory {
+
+    /**
+     * Ecore factory
+     */
+    protected Object factoryImpl = null;
+
+    /**
+     * The identifier of the factory.
+     */
+    protected String id = ""; //$NON-NLS-1$
+
+    /**
+     * The class loader.
+     */
+    protected ClassLoader loader;
+
+    /**
+     * @return the identifier of the factory
+     */
+    protected String getId() {
+        return id;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param factoryId
+     *            is the identifier of the factory
+     * @param ePackage
+     *            is the package
+     * @param loader
+     *            is the class loader
+     * @throws FactoryException
+     */
+    public EFactory(String factoryId, EPackage ePackage, ClassLoader loader) {
+        factoryImpl = ePackage.getEFactoryInstance();
+        id = factoryId;
+        this.loader = loader;
+    }
+
+    /**
+     * Constructor.
+     * <p>
+     * Sample : new Factory("java.resources","Resources") creates an instance of
+     * the factory java.resources.ResourcesFactory
+     * 
+     * @param factoryId
+     *            is the identifier of the factory
+     * @param factoryShortName
+     *            is the factory short name
+     * @param loader
+     *            is the class loader
+     * @throws FactoryException
+     */
+    public EFactory(String factoryId, String factoryShortName, ClassLoader loader) throws FactoryException {
+        this.loader = loader;
+        init(factoryId, factoryShortName, loader); // throws FactoryException
+        // when error
+    }
+
+    private void init(String factoryId, String factoryShortName, ClassLoader loader) throws FactoryException {
+        if (factoryId != null && factoryShortName != null && factoryId.length() > 0 && factoryShortName.length() > 0) {
+            // Class name
+            String rPackageImplClassName = factoryId + '.' + factoryShortName + "Package"; //$NON-NLS-1$
+            // Class loader
+            try {
+                // Class
+                Class rPackageImplClass = Class.forName(rPackageImplClassName, true, loader);
+                // Method
+                Field rPackageImplField = rPackageImplClass.getField("eINSTANCE"); //$NON-NLS-1$
+                Method rPackageImplGetRessourcesFactoryMethod = rPackageImplClass.getMethod("get" + factoryShortName + "Factory", new Class[] {}); //$NON-NLS-1$ //$NON-NLS-2$
+                // Instances
+                Object packageImpl = rPackageImplField.get(null);
+                factoryImpl = rPackageImplGetRessourcesFactoryMethod.invoke(packageImpl, new Object[] {});
+                id = factoryId;
+            } catch (Exception e) {
+                throw new FactoryException(AcceleoEcoreMessages.getString("EFactory.UnexpectedException", new Object[] { e.getMessage(), })); //$NON-NLS-1$
+            }
+        } else {
+            final String factoryName = factoryId + ".impl." + factoryShortName + "FactoryImpl"; //$NON-NLS-1$ //$NON-NLS-2$
+            throw new FactoryException(AcceleoEcoreMessages.getString("EFactory.UnresolvedFactory", new Object[] { factoryName, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Returns the factory path.
+     * 
+     * @return the factory path
+     */
+    public String getPath() {
+        return id;
+    }
+
+    /**
+     * Creates an instance of the classifier whose name is given.
+     * <p>
+     * Sample : Creates an instance of java.resources.Folder if name equals
+     * "Folder" or "resources.Folder".
+     * 
+     * @param name
+     *            is the name of the classifier to be created
+     * @return the new EObject
+     * @throws FactoryException
+     */
+    public EObject eCreate(String name) throws FactoryException {
+        ClassLoader old = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(loader);
+        try {
+            String createName = "create" + name.substring(0, 1).toUpperCase() + name.substring(1); //$NON-NLS-1$
+            return (EObject) EFactory.eCall(factoryImpl, createName, null);
+        } finally {
+            Thread.currentThread().setContextClassLoader(old);
+        }
+    }
+
+    private static Object eCall(Object object, String name, Object arg) throws FactoryException {
+        try {
+            Method method = object.getClass().getMethod(name, (arg != null) ? new Class[] { arg.getClass() } : new Class[] {});
+            return method.invoke(object, (arg != null) ? new Object[] { arg } : new Object[] {});
+        } catch (Exception e) {
+            throw new FactoryException(e.getMessage());
+        }
+    }
+
+    /**
+     * Sets the value of the given feature of the object to the new value.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name of the value to set
+     * @param arg
+     *            is the new value
+     * @throws FactoryException
+     */
+    public static void eSet(EObject object, String name, Object arg) throws FactoryException {
+        EStructuralFeature feature = EFactory.eStructuralFeature(object, name);
+        EFactory.eSet(object, feature, arg);
+    }
+
+    private static void eSet(EObject object, EStructuralFeature feature, Object arg) throws FactoryException {
+        if (!EFactory.eSetEnum(object, feature, arg)) {
+            object.eSet(feature, arg);
+        }
+    }
+
+    private static boolean eSetEnum(EObject object, EStructuralFeature feature, Object arg) {
+        if (feature != null && feature.getEType() instanceof EEnum && arg instanceof String) {
+            try {
+                arg = EFactory.eEnumValue(object, feature, arg);
+                object.eSet(feature, arg);
+            } catch (Exception e) {
+                AcceleoEcorePlugin.getDefault().log(e, false);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private static Object eEnumValue(EObject object, EStructuralFeature feature, Object arg) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
+            IllegalAccessException, InvocationTargetException {
+        String className = ETools.getEClassifierPath(feature.getEType());
+        Class c;
+        try {
+            c = object.getClass().getClassLoader().loadClass(className);
+        } catch (ClassNotFoundException e) {
+            c = Class.forName(className);
+        }
+        Method m = c.getMethod("get", new Class[] { String.class }); //$NON-NLS-1$
+        return m.invoke(c, new Object[] { arg });
+    }
+
+    /**
+     * Sets the value of the given feature of the object to the new value.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name of the value to set
+     * @param arg
+     *            is the new value
+     * @param loader
+     *            is the specific classloader use to set the value
+     * @throws FactoryException
+     */
+    public static void eSet(EObject object, String name, Object arg, ClassLoader loader) throws FactoryException {
+        EStructuralFeature feature = EFactory.eStructuralFeature(object, name);
+        if (feature != null && feature.getEType() instanceof EEnum && arg instanceof String) {
+            try {
+                Class c = loader.loadClass(ETools.getEClassifierPath(feature.getEType()));
+                Method m = c.getMethod("get", new Class[] { String.class }); //$NON-NLS-1$
+                arg = m.invoke(c, new Object[] { arg });
+                object.eSet(feature, arg);
+            } catch (Exception e) {
+                AcceleoEcorePlugin.getDefault().log(e, false);
+            }
+        } else {
+            object.eSet(feature, arg);
+        }
+    }
+
+    /**
+     * Adds the new value of the given feature of the object. If the structural
+     * feature isn't a list, it behaves like eSet.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name of the new value
+     * @param arg
+     *            is the new value
+     * @throws FactoryException
+     */
+    public static void eAdd(EObject object, String name, Object arg) throws FactoryException {
+        EStructuralFeature feature = EFactory.eStructuralFeature(object, name);
+        Object list = object.eGet(feature);
+        if (list != null && list instanceof List) {
+            if (arg != null) {
+                if (feature != null && feature.getEType() instanceof EEnum && arg instanceof String) {
+                    try {
+                        arg = EFactory.eEnumValue(object, feature, arg);
+                        ((List) list).add(arg);
+                    } catch (Exception e) {
+                        AcceleoEcorePlugin.getDefault().log(e, false);
+                    }
+                } else {
+                    ((List) list).add(arg);
+                }
+            }
+        } else {
+            EFactory.eSet(object, feature, arg);
+        }
+    }
+
+    /**
+     * Removes the value of the given feature of the object. If the structural
+     * feature isn't a list, it behaves like eSet(object,name,null).
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name of the value
+     * @param arg
+     *            is the value to remove, null is allowed
+     * @throws FactoryException
+     */
+    public static void eRemove(EObject object, String name, Object arg) throws FactoryException {
+        EStructuralFeature feature = EFactory.eStructuralFeature(object, name);
+        Object list = object.eGet(feature);
+        if (list != null && list instanceof List) {
+            if (arg != null) {
+                if (feature != null && feature.getEType() instanceof EEnum && arg instanceof String) {
+                    try {
+                        arg = EFactory.eEnumValue(object, feature, arg);
+                        ((List) list).remove(arg);
+                    } catch (Exception e) {
+                        AcceleoEcorePlugin.getDefault().log(e, false);
+                    }
+                } else {
+                    ((List) list).remove(arg);
+                }
+            }
+        } else {
+            EFactory.eSet(object, name, null);
+        }
+    }
+
+    /**
+     * Gets the value of the given feature of the object.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name, or a method defined on EObject like
+     *            'eClass', 'eResource', 'eContainer', 'eContainingFeature',
+     *            'eContainmentFeature', 'eContents', 'eAllContents',
+     *            'eCrossReferences'
+     * @return the value of the given feature of the object
+     * @throws FactoryException
+     */
+    public static Object eGet(EObject object, String name) throws FactoryException {
+        return EFactory.eGet(object, name, true);
+    }
+
+    /**
+     * Gets the value of the given feature of the object.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name, or a method defined on EObject like
+     *            'eClass', 'eResource', 'eContainer', 'eContainingFeature',
+     *            'eContainmentFeature', 'eContents', 'eAllContents',
+     *            'eCrossReferences'
+     * @param adaptEnum
+     *            to adapt automatically an enumerator
+     * @return the value of the given feature of the object
+     * @throws FactoryException
+     */
+    public static Object eGet(EObject object, String name, boolean adpatEnum) throws FactoryException {
+        Object result;
+        EStructuralFeature feature = EFactory.doGetFeature(object, name);
+        if (feature != null) {
+            result = object.eGet(feature);
+        } else {
+            try {
+                result = EFactory.eCall(object, name, null);
+            } catch (FactoryException eCall) {
+                throw new FactoryException(AcceleoEcoreMessages.getString("EFactory.UnresolvedLink", new Object[] { name, object.eClass().getName(), })); //$NON-NLS-1$
+            }
+        }
+        if (result != null && result instanceof Enumerator) {
+            if (adpatEnum) {
+                return ((Enumerator) result).getLiteral();
+            } else {
+                return result;
+            }
+        } else if (result != null && result instanceof BasicEList) {
+            List list = new ArrayList();
+            Iterator enums = ((BasicEList) result).iterator();
+            while (enums.hasNext()) {
+                Object next = enums.next();
+                if (adpatEnum && next instanceof Enumerator) {
+                    list.add(((Enumerator) next).getLiteral());
+                } else {
+                    list.add(next);
+                }
+            }
+            return list;
+        } else {
+            return result;
+        }
+    }
+
+    /**
+     * Gets the structural feature of the given feature name of the object.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name
+     * @return the structural feature
+     * @throws FactoryException
+     */
+    public static EStructuralFeature eStructuralFeature(EObject object, String name) throws FactoryException {
+        EStructuralFeature structuralFeature = object.eClass().getEStructuralFeature(name);
+        if (structuralFeature != null) {
+            return structuralFeature;
+        } else {
+            throw new FactoryException(AcceleoEcoreMessages.getString("EFactory.UnresolvedLink", new Object[] { name, object.eClass().getName(), })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Gets the value of the given feature of the object, as an EObject.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name
+     * @return the value or null if it isn't an EObject
+     * @throws FactoryException
+     */
+    public static EObject eGetAsEObject(EObject object, String name) throws FactoryException {
+        Object eGet = EFactory.eGet(object, name);
+        if (eGet != null && eGet instanceof EObject) {
+            return (EObject) eGet;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the value of the given feature of the object, as a String.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name
+     * @return the value or null if it isn't a String
+     * @throws FactoryException
+     */
+    public static String eGetAsString(EObject object, String name) throws FactoryException {
+        Object eGet = EFactory.eGet(object, name);
+        if (eGet != null) {
+            return eGet.toString();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the value of the given feature of the object, as a Boolean.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name
+     * @return the value or null if it isn't a Boolean
+     * @throws FactoryException
+     */
+    public static Boolean eGetAsBoolean(EObject object, String name) throws FactoryException {
+        Object eGet = EFactory.eGet(object, name);
+        if (eGet != null && eGet instanceof Boolean) {
+            return (Boolean) eGet;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the value of the given feature of the object, as an Integer.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name
+     * @return the value or null if it isn't an Integer
+     * @throws FactoryException
+     */
+    public static Integer eGetAsInteger(EObject object, String name) throws FactoryException {
+        Object eGet = EFactory.eGet(object, name);
+        if (eGet != null && eGet instanceof Integer) {
+            return (Integer) eGet;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the value of the given feature of the object, as a List.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name
+     * @return the value, or a new List with a single element if it isn't a
+     *         List, or null if it doesn't exist
+     * @throws FactoryException
+     */
+    public static List eGetAsList(EObject object, String name) throws FactoryException {
+        Object eGet = EFactory.eGet(object, name);
+        if (eGet != null) {
+            if (eGet instanceof List) {
+                return (List) eGet;
+            } else {
+                List list = new BasicEList(1);
+                list.add(eGet);
+                return list;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Indicates if the object is instance of the class whose name is given.
+     * <p>
+     * Samples :
+     * <p>
+     * An instance of java.resources.Folder return true if name equals "Folder"
+     * or "resources.Folder".
+     * <p>
+     * An instance of java.resources.Folder return true if name equals "File"
+     * and Folder inherits File.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the class name
+     * @return true if the object is instance of the class whose name is given
+     */
+    public static boolean eInstanceOf(EObject object, String name) {
+        if (object == null) {
+            return (name == null);
+        }
+        if ("EObject".equals(name) || "ecore.EObject".equals(name)) { //$NON-NLS-1$//$NON-NLS-2$
+            return true;
+        }
+        return EFactory.eInstanceOf(object.eClass(), name);
+    }
+
+    private static boolean eInstanceOf(EClass eClass, String name) {
+        if (name.indexOf('.') == -1 && name.equals(eClass.getName())) {
+            return true;
+        } else {
+            String instanceClassName = '.' + eClass.getInstanceClassName();
+            String endsWith = '.' + name;
+            if (instanceClassName.endsWith(endsWith)) {
+                return true;
+            } else {
+                Iterator superTypes = eClass.getESuperTypes().iterator();
+                while (superTypes.hasNext()) {
+                    EClass eSuperClass = (EClass) superTypes.next();
+                    if (EFactory.eInstanceOf(eSuperClass, name)) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Indicates if the feature name given is valid for the object.
+     * 
+     * @param object
+     *            is the object
+     * @param name
+     *            is the feature name
+     * @return true if the feature is defined, false if not
+     */
+    public static boolean eValid(EObject object, String name) {
+        try {
+            EFactory.eGet(object, name);
+            return true;
+        } catch (FactoryException e) {
+            return false;
+        }
+    }
+
+    private static EStructuralFeature doGetFeature(EObject object, String name) {
+        return object.eClass().getEStructuralFeature(name);
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/factories/FactoryException.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/factories/FactoryException.java
new file mode 100644
index 0000000..eb6629e
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/factories/FactoryException.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.ecore.factories;
+
+import org.eclipse.sirius.query.legacy.tools.log.AcceleoException;
+
+/**
+ * Factory Exception.
+ * 
+ * 
+ */
+public class FactoryException extends AcceleoException {
+
+    private static final long serialVersionUID = 1;
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     */
+    public FactoryException(String message) {
+        super(message);
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/tools/ETools.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/tools/ETools.java
new file mode 100644
index 0000000..0a79065
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/ecore/tools/ETools.java
@@ -0,0 +1,652 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.ecore.tools;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.WeakHashMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.impl.EcorePackageImpl;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.Diagnostician;
+import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.sirius.query.legacy.ecore.AcceleoEcoreMessages;
+import org.eclipse.sirius.query.legacy.ecore.AcceleoEcorePlugin;
+import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoMetamodelProvider;
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+/**
+ * This contains general support for ecore browsing.
+ * 
+ * 
+ */
+public class ETools {
+
+    /**
+     * Returns a URI for the eObject, i.e., either the eProxyURI, the URI of the
+     * eResource with the fragment produced by the eResource, or the URI
+     * consisting of just the fragment that would be produced by a default
+     * Resource with the eObject as its only contents.
+     * 
+     * @param eObject
+     *            the object for which to get the URI.
+     * @return the URI for the object.
+     */
+    public static String getURI(EObject object) {
+        if (object == null) {
+            return ""; //$NON-NLS-1$
+        } else if (object.eResource() != null) {
+            return object.eResource().getURIFragment(object);
+        } else {
+            // inspired from EMF sources
+            StringBuffer result = new StringBuffer("//"); //$NON-NLS-1$
+            List uriFragmentPath = new ArrayList();
+            for (EObject container = object.eContainer(); container != null; container = object.eContainer()) {
+                uriFragmentPath.add(((InternalEObject) container).eURIFragmentSegment(object.eContainmentFeature(), object));
+                object = container;
+            }
+            int size = uriFragmentPath.size();
+            if (size > 0) {
+                for (int i = size - 1;; --i) {
+                    result.append((String) uriFragmentPath.get(i));
+                    if (i == 0) {
+                        break;
+                    } else {
+                        result.append('/');
+                    }
+                }
+            }
+            return result.toString();
+        }
+    }
+
+    /**
+     * It validates the given EMF object.
+     * <p>
+     * An error is put in the acceleo log if the validation failed.
+     * <p>
+     * <li>!blocker || Diagnostic.OK => root</li>
+     * <li>blocker && !Diagnostic.OK => null</li>
+     * <li>root == null => null</li>
+     * 
+     * @param root
+     *            is the object to validate
+     * @param blocker
+     *            indicates if the result must be Diagnostic.OK
+     * @param message
+     *            is the error message to put in the acceleo log
+     * @return the given object or null
+     */
+    public static EObject validate(EObject root, boolean blocker, String message) {
+        if (root != null && !(root.getClass().getName().startsWith("org.eclipse.uml2"))) { //$NON-NLS-1$
+            if (Diagnostician.INSTANCE.validate(root).getSeverity() != Diagnostic.OK) {
+                AcceleoEcorePlugin.getDefault().log(message, blocker);
+                if (blocker) {
+                    return null;
+                }
+            }
+        }
+        return root;
+    }
+
+    /**
+     * Creates root package for the metamodel nsURI or the metamodel file path.
+     * <p>
+     * uri2EPackage(path,true)
+     * 
+     * @param path
+     *            is the metamodel nsURI or the metamodel file path
+     * @return the root package of the metamodel
+     */
+    public static EPackage uri2EPackage(String path) {
+        return ETools.uri2EPackage(path, true);
+    }
+
+    /**
+     * Creates root package for the metamodel nsURI or the metamodel file path.
+     * 
+     * @param path
+     *            is the metamodel nsURI or the metamodel file path
+     * @param forceReload
+     *            indicates that the reload of the metamodel is forced, if
+     *            forceReload is false then file modification stamp is used for
+     *            optimization
+     * @return the root package of the metamodel
+     */
+    public static EPackage uri2EPackage(String path, boolean forceReload) {
+        if (path != null && path.length() > 0) {
+            path = path.trim();
+            EPackage regValue = EPackage.Registry.INSTANCE.getEPackage(path);
+            if (regValue != null) {
+                return regValue;
+            } else {
+                return ETools.ecore2EPackage(path, forceReload);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Creates root package for the ecore file path.
+     * 
+     * @param path
+     *            is the ecore file path
+     * @param forceReload
+     *            indicates that the reload of the metamodel is forced, if
+     *            forceReload is false then file modification stamp is used
+     * @return the root package of the metamodel
+     */
+    private static EPackage ecore2EPackage(String path, boolean forceReload) {
+        IPath ecorePath = new Path(path);
+        if (ecorePath.segmentCount() >= 2) {
+            path = ecorePath.removeFileExtension().addFileExtension("ecore").toString(); //$NON-NLS-1$
+            IFile ecoreFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
+            if (ecoreFile != null && ecoreFile.exists()) {
+                if (forceReload) {
+                    return ETools.subEcore2EPackage(path, false);
+                } else {
+                    EPackage ePackage = (EPackage) ETools.ecore2EPackage.get(path);
+                    Double newModificationStamp = new Double(ecoreFile.getModificationStamp());
+                    Double oldModificationStamp = (Double) ETools.ecore2OldModificationStamp.get(path);
+                    if (ePackage == null || oldModificationStamp == null || oldModificationStamp.doubleValue() != newModificationStamp.doubleValue()) {
+                        ePackage = ETools.subEcore2EPackage(path, false);
+                        ETools.ecore2EPackage.put(path, ePackage);
+                        ETools.ecore2OldModificationStamp.put(path, newModificationStamp);
+                    }
+                    return ePackage;
+                }
+            } else {
+                File file = AcceleoMetamodelProvider.getDefault().getFile(new Path(path));
+                if (file != null && file.exists()) {
+                    path = file.getAbsolutePath();
+                    if (forceReload) {
+                        return ETools.subEcore2EPackage(path, true);
+                    } else {
+                        EPackage ePackage = (EPackage) ETools.ecore2EPackage.get(path);
+                        if (ePackage == null) {
+                            ePackage = ETools.subEcore2EPackage(path, true);
+                            ETools.ecore2EPackage.put(path, ePackage);
+                            ETools.ecore2OldModificationStamp.put(path, null);
+                        }
+                        return ePackage;
+                    }
+                } else {
+                    return null;
+                }
+            }
+        }
+        return null;
+    }
+
+    private static Map ecore2EPackage = new WeakHashMap();
+
+    private static Map ecore2OldModificationStamp = new HashMap();
+
+    private static EPackage subEcore2EPackage(String path, boolean isExternal) {
+        URI ecoreURI;
+        if (isExternal) {
+            ecoreURI = URI.createFileURI(path);
+        } else {
+            ecoreURI = Resources.createPlatformResourceURI(path);
+        }
+        Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
+        reg.getExtensionToFactoryMap().put("ecore", new EcoreResourceFactoryImpl()); //$NON-NLS-1$
+        ResourceSet ecoreResourceSet = new ResourceSetImpl();
+        Resource ecoreResource = ecoreResourceSet.getResource(ecoreURI, true);
+        Object result = (ecoreResource.getContents().size() > 0) ? ecoreResource.getContents().get(0) : null;
+        if (result instanceof EPackage) {
+            String nsURI = ETools.getNsURI((EPackage) result);
+            if (nsURI != null) {
+                EPackage regValue = EPackage.Registry.INSTANCE.getEPackage(nsURI);
+                if (regValue != null) {
+                    return regValue;
+                }
+            }
+            return (EPackage) ETools.validate((EPackage) result, false, AcceleoEcoreMessages.getString("ETools.ModelValidationNeeded", new Object[] { path, })); //$NON-NLS-1$
+        } else {
+            return null;
+        }
+    }
+
+    private static String getNsURI(EPackage p) {
+        String pNsURI = p.getNsURI();
+        if (pNsURI != null && pNsURI.length() > 0) {
+            return pNsURI;
+        }
+        if (p.getESubpackages().size() == 1) {
+            return ETools.getNsURI(p.getESubpackages().get(0));
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Search all the classifiers recursively in a package.
+     * 
+     * @param ePackage
+     *            is the container
+     * @return table of classifiers
+     */
+    public static EClassifier[] computeAllClassifiers(EPackage ePackage) {
+        List classifiers = ETools.computeAllClassifiersList(ePackage);
+        return (EClassifier[]) classifiers.toArray(new EClassifier[] {});
+    }
+
+    /**
+     * Search all the classifiers recursively in a package.
+     * 
+     * @param ePackage
+     *            is the container
+     * @return list of classifiers
+     */
+    public static List computeAllClassifiersList(EPackage ePackage) {
+        return ETools.computeAllClassifiersList(ePackage, false);
+    }
+
+    /**
+     * Search all the classifiers recursively in a package.
+     * 
+     * @param ePackage
+     *            is the container
+     * @param classOnly
+     *            indicates that only the classes are kept
+     * @return list of classifiers
+     */
+    public static List computeAllClassifiersList(EPackage ePackage, boolean classOnly) {
+        List classifiers = new BasicEList();
+        if (ePackage != null) {
+            ETools.computeAllClassifiersList(ePackage, classifiers, classOnly);
+        }
+        return classifiers;
+    }
+
+    private static void computeAllClassifiersList(EPackage ePackage, List all, boolean classOnly) {
+        Iterator classifiers = ePackage.getEClassifiers().iterator();
+        while (classifiers.hasNext()) {
+            EClassifier classifier = (EClassifier) classifiers.next();
+            if (!classOnly) {
+                all.add(classifier);
+            } else {
+                if (classifier instanceof EClass && !((EClass) classifier).isAbstract() && !((EClass) classifier).isInterface()) {
+                    all.add(classifier);
+                }
+            }
+        }
+        Iterator packages = ePackage.getESubpackages().iterator();
+        while (packages.hasNext()) {
+            ETools.computeAllClassifiersList((EPackage) packages.next(), all, classOnly);
+        }
+    }
+
+    /**
+     * Search a classifier recursively in a package.
+     * <p>
+     * Remarks :
+     * <li>It never returns classifier java.resources.Folder if name = "File"</li>
+     * <li>It never returns classifier java.resources.Folder if name = "older"</li>
+     * <li>It returns classifier java.resources.Folder for "Folder" or
+     * "resources.Folder"</li>
+     * 
+     * @param ePackage
+     *            is the container
+     * @param name
+     *            is the classifier identifier
+     * @return classifier or null if not found
+     */
+    public static EClassifier getEClassifier(EPackage ePackage, String name) {
+        if (ePackage == null || name == null) {
+            return null;
+        }
+        name = name.trim();
+        EClassifier get = null;
+        /*
+         * Special case for EObject as we want a generic type for all the
+         * elements.
+         */
+        if (name.equals("EObject") || name.equals("ecore.EObject")) { //$NON-NLS-1$ //$NON-NLS-2$
+            get = EcorePackage.eINSTANCE.getEObject();
+        }
+        Iterator classifiers = ePackage.getEClassifiers().iterator();
+        while (get == null && classifiers.hasNext()) {
+            EClassifier classifier = (EClassifier) classifiers.next();
+            String instanceClassName = '.' + ETools.getEClassifierPath(classifier);
+            String endsWith = '.' + name;
+            if (instanceClassName.endsWith(endsWith)) {
+                get = classifier;
+            }
+        }
+        Iterator packages = ePackage.getESubpackages().iterator();
+        while (get == null && packages.hasNext()) {
+            EClassifier classifier = ETools.getEClassifier((EPackage) packages.next(), name);
+            if (classifier != null) {
+                get = classifier;
+            }
+        }
+        return get;
+    }
+
+    /**
+     * Returns the feature with this classifier and this name.
+     * 
+     * @param currentEClassifier
+     *            is the classifier
+     * @param name
+     *            is the feature name
+     * @return the feature
+     */
+    public static EStructuralFeature getEStructuralFeature(EClassifier currentEClassifier, String name) {
+        if (currentEClassifier != null && currentEClassifier instanceof EClass) {
+            return ETools.getEStructuralFeature((EClass) currentEClassifier, name);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the feature with this class and this name.
+     * 
+     * @param currentEClass
+     *            is the class
+     * @param name
+     *            is the feature name
+     * @return the feature
+     */
+    public static EStructuralFeature getEStructuralFeature(EClass currentEClass, String name) {
+        name = name.trim();
+        if (currentEClass != null) {
+            return currentEClass.getEStructuralFeature(name);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns a factory name for a classifier. There is a factory by package.
+     * The factory is used to create instances of classifiers.
+     * <p>
+     * Sample : "ResourcesFactory" is the name of the factory
+     * java.resources.ResourcesFactory
+     * 
+     * @param eClassifier
+     *            is the classifier
+     * @return the factory name
+     */
+    public static String getEClassifierFactoryName(EClassifier eClassifier) {
+        return ETools.getEClassifierFactoryShortName(eClassifier) + "Factory"; //$NON-NLS-1$
+    }
+
+    /**
+     * Returns a factory short name for a classifier. There is a factory by
+     * package. The factory is used to create instances of classifiers.
+     * <p>
+     * Sample : "Resources" is the short name of the factory
+     * java.resources.ResourcesFactory
+     * 
+     * @param eClassifier
+     *            is the classifier
+     * @return the factory short name
+     */
+    public static String getEClassifierFactoryShortName(EClassifier eClassifier) {
+        if (eClassifier != null) {
+            EPackage p = eClassifier.getEPackage();
+            String name = p.getName();
+            if (name != null && name.length() > 0) {
+                return name.substring(0, 1).toUpperCase() + name.substring(1);
+            }
+        }
+        return ""; //$NON-NLS-1$
+    }
+
+    /**
+     * Returns the full path of the classifier.
+     * <p>
+     * Sample : "java.resources.JavaFile" is the full path for the classifier
+     * java.resources.JavaFile
+     * 
+     * @param eClassifier
+     *            is the classifier
+     * @return full path of the classifier
+     */
+    public static String getEClassifierPath(EClassifier eClassifier) {
+        if (eClassifier != null) {
+            String instanceClassName = eClassifier.getInstanceClassName();
+            String name = eClassifier.getName();
+            if (eClassifier.getEPackage() != null) {
+                EPackage container = eClassifier.getEPackage();
+                if (container != null && instanceClassName != null && instanceClassName.endsWith(container.getName() + '.' + name)) {
+                    return instanceClassName;
+                }
+                while (container != null) {
+                    name = container.getName() + '.' + name;
+                    container = container.getESuperPackage();
+                }
+            }
+            return name;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the short path of the classifier.
+     * <p>
+     * Sample : "resources.JavaFile" is the short path for the classifier
+     * java.resources.JavaFile
+     * 
+     * @param eClassifier
+     *            is the classifier
+     * @return short path of the classifier
+     */
+    public static String getEClassifierShortPath(EClassifier eClassifier) {
+        String name = eClassifier.getName();
+        if (eClassifier.getEPackage() != null) {
+            name = eClassifier.getEPackage().getName() + '.' + name;
+        }
+        return name;
+    }
+
+    /**
+     * Creates a package and his children in an ecore model. The children are
+     * separated by '.'
+     * <p>
+     * Sample : "a.b.c" is a package full path,
+     * <p>
+     * "a", "b", and "c" packages are created, the root package "a" is returned.
+     * 
+     * @param path
+     *            is the package full path
+     * @return the root package
+     */
+    public static EPackage createPackageHierarchy(String path) {
+        EPackage ePackage = null;
+        if (path != null && path.length() > 0) {
+            EcorePackage p = EcorePackageImpl.init();
+            EcoreFactory factory = p.getEcoreFactory();
+            EPackage parent = null;
+            StringTokenizer st = new StringTokenizer(path, "."); //$NON-NLS-1$
+            while (st.hasMoreTokens()) {
+                String name = st.nextToken();
+                EPackage child = factory.createEPackage();
+                child.setName(name);
+                if (parent != null) {
+                    parent.getESubpackages().add(child);
+                } else {
+                    ePackage = child;
+                }
+                parent = child;
+            }
+        }
+        return ePackage;
+    }
+
+    /**
+     * Get a package in a parent package.
+     * <p>
+     * Sample : "a.b" is a parent package and "c.d" is a relative path,
+     * <p>
+     * "a.b.c.d" package is returned.
+     * 
+     * @param parent
+     *            is the parent package
+     * @param path
+     *            is the relative path of the required package
+     * @return the required package, null if not found
+     */
+    public static EPackage getEPackage(EPackage parent, String path) {
+        EPackage ePackage = parent;
+        if (path != null && path.length() > 0) {
+            StringTokenizer st = new StringTokenizer(path, "."); //$NON-NLS-1$
+            while (st.hasMoreTokens()) {
+                String name = st.nextToken();
+                boolean found = false;
+                Iterator subPackages = ePackage.getESubpackages().iterator();
+                while (!found && subPackages.hasNext()) {
+                    EPackage subPackage = (EPackage) subPackages.next();
+                    if (subPackage.getName().equals(name)) {
+                        found = true;
+                        ePackage = subPackage;
+                    }
+                }
+                if (!found) {
+                    return null;
+                }
+            }
+        }
+        return ePackage;
+    }
+
+    /**
+     * Indicates if an instance of the classifier is an instance of the type.
+     * 
+     * @param classifier
+     *            is the classifier
+     * @param type
+     *            is the type
+     * @return true if an instance of the classifier is an instance of the type
+     */
+    public static boolean ofType(EClassifier classifier, String type) {
+        if (classifier instanceof EClass) {
+            return ETools.ofType((EClass) classifier, type);
+        } else {
+            return ETools.ofClass(classifier, type);
+        }
+    }
+
+    /**
+     * Indicates if an instance of the class is an instance of the type.
+     * 
+     * @param eClass
+     *            is the class
+     * @param type
+     *            is the type
+     * @return true if an instance of the class is an instance of the type
+     */
+    public static boolean ofType(EClass eClass, String type) {
+        if ("EObject".equalsIgnoreCase(type) || "ecore.EObject".equalsIgnoreCase(type) || ETools.ofClass(eClass, type)) {
+            return true;
+        }
+        Iterator superTypes = eClass.getESuperTypes().iterator();
+        while (superTypes.hasNext()) {
+            EClassifier superType = (EClassifier) superTypes.next();
+            if (ETools.ofType(superType, type)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Indicates if the type corresponds to the name of the classifier.
+     * 
+     * @param classifier
+     *            is the classifier
+     * @param type
+     *            is the type
+     * @return true if the type corresponds to the name of the classifier
+     */
+    public static boolean ofClass(EClassifier classifier, String type) {
+        String path = ETools.getEClassifierPath(classifier);
+        return ('.' + path).endsWith('.' + type);
+    }
+
+    /**
+     * Loads an EMF model.
+     * 
+     * @param path
+     *            is the path of the model to load
+     * @return the root element of the model
+     */
+    public static EObject loadXMI(String path) {
+        return ETools.loadXMI(path, null);
+    }
+
+    /**
+     * Loads an EMF model, using a specific resource factory (using UML resource
+     * for an XMI file)
+     * 
+     * @param path
+     *            is the path of the model to load
+     * @param resourceFactoryExtension
+     *            is the resource factory default extension, for example "uml",
+     *            can be null
+     * 
+     * @return the root element of the model
+     */
+    public static EObject loadXMI(String path, String resourceFactoryExtension) {
+        URI modelURI = Resources.createPlatformResourceURI(path);
+        String fileExtension = modelURI.fileExtension();
+        if (fileExtension == null || fileExtension.length() == 0) {
+            fileExtension = Resource.Factory.Registry.DEFAULT_EXTENSION;
+        }
+        ResourceSet resourceSet = new ResourceSetImpl();
+        Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
+        Object resourceFactory;
+        if (resourceFactoryExtension != null) {
+            resourceFactory = reg.getExtensionToFactoryMap().get(resourceFactoryExtension);
+        } else {
+            resourceFactory = reg.getExtensionToFactoryMap().get(fileExtension);
+        }
+        if (resourceFactory != null) {
+            resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(fileExtension, resourceFactory);
+        } else {
+            resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(fileExtension, new XMIResourceFactoryImpl());
+        }
+        Resource modelResource = resourceSet.getResource(modelURI, true);
+        return ((modelResource.getContents().size() > 0) ? modelResource.getContents().get(0) : null);
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/AcceleoEcoreGenPlugin.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/AcceleoEcoreGenPlugin.java
new file mode 100644
index 0000000..b02572c
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/AcceleoEcoreGenPlugin.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen;
+
+import java.io.File;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.osgi.framework.BundleContext;
+
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.ISpecificScriptContext;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.tools.resources.AcceleoPlugin;
+import org.eclipse.sirius.query.legacy.tools.resources.FileContentMap;
+
+/**
+ * The main plugin class to be used in the desktop.
+ * 
+ * 
+ */
+public class AcceleoEcoreGenPlugin extends AcceleoPlugin {
+
+    /* (non-Javadoc) */
+    @Override
+    public String getID() {
+        return "org.eclipse.sirius.query.legacy.gen"; //$NON-NLS-1$
+    }
+
+    /**
+     * The shared instance.
+     */
+    private static AcceleoEcoreGenPlugin plugin;
+
+    /**
+     * Resource bundle.
+     */
+    private ResourceBundle resourceBundle;
+
+    /**
+     * The global script context.
+     */
+    private SpecificScriptContext globalScriptContext;
+
+    private class SpecificScriptContext implements ISpecificScriptContext {
+
+        private int maxLevel;
+
+        private FileContentMap contextFile2Script = new FileContentMap(true);
+
+        /**
+         * Constructor.
+         * 
+         * @param maxLevel
+         *            is the maximum level of the context
+         */
+        public SpecificScriptContext(int maxLevel) {
+            this.maxLevel = maxLevel;
+        }
+
+        /* (non-Javadoc) */
+        public SpecificScript getScript(File file, File chainFile) {
+            SpecificScript result = (SpecificScript) contextFile2Script.get(file);
+            if (result != null) {
+                result.setChainFile(chainFile);
+                return result;
+            } else {
+                return null;
+            }
+        }
+
+        /* (non-Javadoc) */
+        public void setScript(File file, SpecificScript script) {
+            if (script != null) {
+                contextFile2Script.put(file, script);
+            }
+        }
+
+        /* (non-Javadoc) */
+        public int getMaxLevel() {
+            return maxLevel;
+        }
+
+    };
+
+    /**
+     * The constructor.
+     */
+    public AcceleoEcoreGenPlugin() {
+        super();
+        AcceleoEcoreGenPlugin.plugin = this;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public void start(BundleContext context) throws Exception {
+        super.start(context);
+        TemplateConstants.initConstants();
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        super.stop(context);
+        AcceleoEcoreGenPlugin.plugin = null;
+        resourceBundle = null;
+        globalScriptContext = null;
+    }
+
+    /**
+     * @return the shared instance
+     */
+    public static AcceleoEcoreGenPlugin getDefault() {
+        return AcceleoEcoreGenPlugin.plugin;
+    }
+
+    /**
+     * Returns the string from the plugin's resource bundle, or 'key' if not
+     * found.
+     * 
+     * @param key
+     *            identifies the string
+     * @return the string from the plugin's resource bundle, or 'key' if not
+     *         found
+     */
+    public static String getResourceString(String key) {
+        ResourceBundle bundle = AcceleoEcoreGenPlugin.getDefault().getResourceBundle();
+        try {
+            return (bundle != null) ? bundle.getString(key) : key;
+        } catch (MissingResourceException e) {
+            return key;
+        }
+    }
+
+    /**
+     * Returns the plugin's resource bundle.
+     * 
+     * @return the plugin's resource bundle
+     */
+    public ResourceBundle getResourceBundle() {
+        try {
+            if (resourceBundle == null) {
+                resourceBundle = ResourceBundle.getBundle("org.eclipse.sirius.query.legacy.gen.AcceleoEcoreGenPluginResources"); //$NON-NLS-1$
+            }
+        } catch (MissingResourceException x) {
+            resourceBundle = null;
+        }
+        return resourceBundle;
+    }
+
+    /**
+     * @return the global script context
+     */
+    public ISpecificScriptContext getGlobalScriptContext() {
+        if (globalScriptContext == null) {
+            globalScriptContext = new SpecificScriptContext(2);
+        }
+        return globalScriptContext;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/AcceleoGenMessages.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/AcceleoGenMessages.java
new file mode 100644
index 0000000..b40008a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/AcceleoGenMessages.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.query.legacy.gen;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class to access externalized Strings for Acceleo's gen.
+ * 
+ */
+public final class AcceleoGenMessages {
+    /** Full qualified path to the properties file in which to seek the keys. */
+    private static final String BUNDLE_NAME = "org.eclipse.sirius.query.legacy.gen.acceleogenmessages"; //$NON-NLS-1$
+
+    /** Contains the locale specific {@link String}s needed by this plug-in. */
+    private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(AcceleoGenMessages.BUNDLE_NAME);
+
+    /**
+     * Utility classes don't need to (and shouldn't) be instantiated.
+     */
+    private AcceleoGenMessages() {
+        // prevents instantiation
+    }
+
+    /**
+     * Returns a specified {@link String} from the resource bundle.
+     * 
+     * @param key
+     *            Key of the String we seek.
+     * @return The String from the resource bundle associated with
+     *         <code>key</code>.
+     */
+    public static String getString(String key) {
+        try {
+            return AcceleoGenMessages.getString(key, new Object[] {});
+        } catch (MissingResourceException e) {
+            return '!' + key + '!';
+        }
+    }
+
+    /**
+     * Returns a String from the resource bundle binded with the given
+     * arguments.
+     * 
+     * @param key
+     *            Key of the String we seek.
+     * @param arguments
+     *            Arguments for the String formatting.
+     * @return formatted {@link String}.
+     * @see MessageFormat#format(String, Object[])
+     */
+    public static String getString(String key, Object[] arguments) {
+        if (arguments == null) {
+            return MessageFormat.format(AcceleoGenMessages.RESOURCE_BUNDLE.getString(key), new Object[] {});
+        }
+        return MessageFormat.format(AcceleoGenMessages.RESOURCE_BUNDLE.getString(key), arguments);
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/acceleogenmessages.properties b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/acceleogenmessages.properties
new file mode 100644
index 0000000..8b67d17
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/acceleogenmessages.properties
@@ -0,0 +1,131 @@
+#===============================================================================
+# Copyright (c) 2005-2014 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:
+#    Obeo - initial API and implementation
+#===============================================================================
+## NOTE TO TRANSLATORS : apostrophes (') need to be doubled if you need one displayed
+## General keys
+UnresolvedExtensionPoint = Extension-point {0} could not be resolved
+
+ENodeError.BooleanRequired = Boolean expression required while detected type is {0}
+ENodeError.EmptyEvaluation = Empty feature evaluation
+ENodeError.UnresolvedTemplate = Template {0} does not exist
+ENodeError.UnresolvedRoot = Root template does not exist
+
+TemplateSyntaxError.DuplicateEntry.Text = Duplicate text template entry detected : {0}
+TemplateSyntaxError.DuplicateEntry.File = Duplicate file template entry detected : {0}
+TemplateSyntaxError.DuplicateValue = The {0} value is duplicated
+TemplateSyntaxError.EmptyUserTag = User tag line cannot be empty
+TemplateSyntaxError.EmptyValue = The {0} value is required
+TemplateSyntaxError.InvalidCharacter = Character {0} is invalid
+TemplateSyntaxError.InvalidImportSequence = The import sequence is invalid
+TemplateSyntaxError.InvalidKey = The key {0} is invalid
+TemplateSyntaxError.InvalidKeyValue = Value of the key {0} is invalid
+TemplateSyntaxError.InvalidLitteral = Litteral element is not valid
+TemplateSyntaxError.InvalidSequence = Sequence is not valid
+TemplateSyntaxError.MissingCloseBracket = Closing bracket not found
+TemplateSyntaxError.MissingCloseIf = "If" statement must be closed
+TemplateSyntaxError.MissingCloseParenthesis = Closing parenthesis not found
+TemplateSyntaxError.MissingCommentEndTag = Comment end tag not found
+TemplateSyntaxError.MissingElement = Required element not found
+TemplateSyntaxError.MissingKeyValue = Value of the key {0} is missing
+TemplateSyntaxError.MissingKeyWord = The {0} keyword is required
+TemplateSyntaxError.MissingName = Name is missing
+TemplateSyntaxError.MissingScriptEndTag = Script end tag not found
+TemplateSyntaxError.MissingType = Type is missing
+TemplateSyntaxError.RecursiveDependency = Recursive dependency detected
+TemplateSyntaxError.RecursiveImport = Recursive import detected
+TemplateSyntaxError.UnresolvedCall = Unresolved call "{0}"
+TemplateSyntaxError.UnresolvedClassifier = Classifier {0} not found in the metamodel
+TemplateSyntaxError.UnresolvedImport = Unresolved import {0}
+TemplateSyntaxError.UnresolvedMetamodel = Unresolved metamodel
+TemplateSyntaxError.BadOverride = Import {0} should be moved up in the import list.
+
+## org.eclipse.sirius.query.legacy.gen.phantom
+ChainPhantomProvider.InvalidFile = file content is invalid
+
+## org.eclipse.sirius.query.legacy.gen.template
+Template.UnclosedTag = {0} is required to close {1}
+Template.RecursiveCall = Recursive template call detected in template {0}
+
+TemplateSyntaxExceptions.ErrorInFile = Compilation error in the file : {0}
+TemplateSyntaxExceptions.ErrorUnknownFile = Compilation error
+TemplateSyntaxExceptions.ErrorExportFile = Export issue for the file : {0}
+
+## org.eclipse.sirius.query.legacy.gen.template.eval
+ENode.InvalidAdapterType = {0} is not a valid adapter type.
+ENode.AdapterNotFound = {0} adapter not found for node {1}
+ENode.ENodeCastExceptionMessage = Type {0} found when {1} was required
+
+# NOTE : These allow the redefinition of an exception message. They will for the most part be
+# concatened one after the other and thus need to stay separated (comma-separated in english).
+# as an exemple, we could end with a final String looking like (XXX being the {x}
+# substitutions) :
+# XXX, in file XXX, at line : XXX, at column : XXX, for object : fragment=XXX file=XXX
+ENodeException.ExtendedErrorMessage.KnownFile = {0}, in file : {1}, at line : {2}, at column : {3}
+ENodeException.ExtendedErrorMessage.UnknownFile = {0}, at position [{1},{2}]
+ENodeException.ExtendedErrorMessage.NodeFragment = , for node "{0}"
+ENodeException.ExtendedErrorMessage.ObjectFragmentKnownResource = , for object : fragment={0} file={1}
+ENodeException.ExtendedErrorMessage.ObjectFragmentUnknownResource = , for object : fragment={0} type={1} value={2}
+
+## org.eclipse.sirius.query.legacy.gen.template.eval.log
+# NOTE : This is displayed as the error message when a template evaluation fails. "EVAL" are
+# the first four letters of "evaluation", translate as you would translate "evaluation" if
+# there are no abbreviation counterpart in your target language.
+EvalFailure.FailureMessage = EVAL : {0}
+EvalFailure.FailurePosition = Position {0}
+
+## org.eclipse.sirius.query.legacy.gen.template.eval.merge
+MergeTools.MovedCode = This part of the code has been moved from "{0}" to "{1}"
+MergeTools.DuplicatedTag = Duplicated tag "{0}"
+
+## org.eclipse.sirius.query.legacy.gen.template.expressions
+ExpressionTools.InvalidExpression = Expression {0} is not valid.
+ExpressionTools.ZeroDivide = Cannot divide by 0.
+ExpressionTools.AdapterNotFound = Double adapter not found for operation "{0}" : {1}
+
+TemplateCallExpression.UnresolvedCall = Unresolved call "{0}"
+
+TemplateCallSetExpression.UnresolvedArgument = The argument {0} does not exist
+TemplateCallSetExpression.InvalidArgument = Type of the argument isn't valid
+
+## org.eclipse.sirius.query.legacy.gen.template.scripts
+SpecificScript.ErroneousTemplate = The template contains errors.
+
+## org.eclipse.sirius.query.legacy.gen.template.scripts.imports
+# NOTE : "Runtime" refers to a "runtime error". Translate as needed.
+EvalJavaService.RuntimeException = Runtime : Java service [{0}] throws : {1}
+EvalJavaService.RuntimeType = Runtime : Java service [{0}] returns wrong type : {1}
+EvalJavaService.UnresolvedService = Java service issue : {0}
+
+EvalModel.EvaluationEmptyNaming = Evaluating {0} on {1} because {2}.naming is empty
+
+## org.eclipse.sirius.query.legacy.gen.template.scripts.import.services
+ENodeServices.TraceMessage = type={0} value={1}
+
+## org.eclipse.sirius.query.legacy.gen.runner
+AcceleoGenerate.Task.OpeningModel = Open Model {0}
+AcceleoGenerate.Task.Generate = Generating file : {0}
+AcceleoGenerate.MissingModel = Model {0} does not exist
+AcceleoGenerate.MissingTemplate = Template {0} does not exist
+AcceleoGenerate.MissingTarget = Target folder {0} does not exist
+AcceleoGenerate.MissingAcceleoIni = The file {0} does not exist in your install location
+AcceleoGenerate.UnresolvedTemplate = Generator template not found
+AcceleoGenerate.ErrorReport = Errors in file : {0}
+AcceleoGenerate.LostCode = Lost Code
+AcceleoGenerate.UnresolvedProperties = Properties container not found : {0}
+AcceleoGenerate.AcceleoIniLineIssue = Line {0} not valid in the file {1}
+
+#############################################
+#       END OF TRANSLATED PROPERTIES        #
+# do not translate values beyond this point #
+#############################################
+## org.eclipse.sirius.query.legacy.gen.template.eval.merge
+MergeTools.UserCodeStart = Start of user code
+MergeTools.UserCodeEnd = End of user code
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/Template.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/Template.java
new file mode 100644
index 0000000..7d372fc
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/Template.java
@@ -0,0 +1,762 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.EFactory;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoEcoreGenPlugin;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.eval.TextModelMapping;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.ScriptDescriptor;
+import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateCommentStatement;
+import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateFeatureStatement;
+import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateForStatement;
+import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateIfStatement;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * This is a template for the generation tool. This class provides services such
+ * as :
+ * <ul>
+ * <li>Simple template initialization methods.
+ * <li>Functions to apply the template to model's objects to allow dynamic
+ * generation.
+ * </ul>
+ * 
+ * 
+ */
+public class Template extends TemplateNodeElement {
+
+    /**
+     * Empty template reference.
+     */
+    public static final Template EMPTY = new Template(null);
+
+    /**
+     * The descriptor of this template.
+     */
+    protected ScriptDescriptor descriptor = null;
+
+    /**
+     * The post expression.
+     */
+    protected TemplateExpression postExpression = null;
+
+    /**
+     * Indicates if the last evaluation returned an empty node.
+     */
+    protected boolean emptyEvaluation = true;
+
+    /**
+     * Nodes of the template.
+     */
+    protected List elements = new ArrayList();
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public Template(IScript script) {
+        super(script);
+    }
+
+    /**
+     * @return the descriptor of this template
+     */
+    public ScriptDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    /**
+     * @param descriptor
+     *            is the descriptor of this template
+     */
+    public void setDescriptor(ScriptDescriptor descriptor) {
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * @return the post expression
+     */
+    public TemplateExpression getPostExpression() {
+        return postExpression;
+    }
+
+    /**
+     * @param postExpression
+     *            is the post expression
+     */
+    public void setPostExpression(TemplateExpression postExpression) {
+        this.postExpression = postExpression;
+    }
+
+    /**
+     * Indicates if the last evaluation returned an empty node.
+     * 
+     * @return true if the last evaluation returned an empty node
+     */
+    public boolean isEmptyEvaluation() {
+        return emptyEvaluation;
+    }
+
+    /**
+     * It saves template's state.
+     * 
+     * @return the template's state
+     */
+    public Object copyState() {
+        return new ArrayList(elements);
+    }
+
+    /**
+     * It restores template's state.
+     * 
+     * @param state
+     *            is the template's state to be restored
+     */
+    public void fromState(Object state) {
+        elements = (List) state;
+    }
+
+    /**
+     * Removes all of the elements from this template.
+     */
+    public void clear() {
+        elements.clear();
+    }
+
+    /**
+     * Appends the specified element to the end of this template.
+     * 
+     * @param element
+     *            is the element to be added
+     */
+    public void append(TemplateNodeElement element) {
+        if (element instanceof TemplateText) {
+            if (((TemplateText) element).text.length() > 0) {
+                elements.add(element);
+                element.setParent(this);
+            }
+        } else if (element != null) {
+            elements.add(element);
+            element.setParent(this);
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        final StringBuffer text = new StringBuffer(""); //$NON-NLS-1$
+        final Iterator it = elements.iterator();
+        while (it.hasNext()) {
+            final TemplateNodeElement element = (TemplateNodeElement) it.next();
+            text.append(element.toString());
+        }
+        return text.toString();
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getOutlineText() {
+        return ""; //$NON-NLS-1$
+    }
+
+    /**
+     * It creates a dynamic template for the given text.
+     * 
+     * @param buffer
+     *            is the textual representation of the new template
+     * @param script
+     *            is the generator's configuration used to apply the new
+     *            template to model's objects
+     * @param object
+     *            is the object to select when an error is detected
+     * @return the new template
+     * @throws ENodeException
+     */
+    public static Template from(String buffer, IScript script, EObject object) throws ENodeException {
+        try {
+            return Template.read(buffer, script);
+        } catch (final TemplateSyntaxException e) {
+            throw new ENodeException(e.getMessage(), e.getPos(), script, object, true);
+        }
+    }
+
+    /**
+     * It checks the syntax of the new template text and creates a template for
+     * the given text.
+     * 
+     * @param buffer
+     *            is the textual representation of the new template
+     * @param script
+     *            is the generator's configuration used to apply the new
+     *            template to model's objects
+     * @return the new template
+     * @throws TemplateSyntaxException
+     */
+    private static Template read(String buffer, IScript script) throws TemplateSyntaxException {
+        return Template.read(buffer, new Int2(0, buffer.length()), script);
+    }
+
+    /**
+     * It checks the syntax and creates a template for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param buffer
+     *            is the textual representation of the script that contains
+     *            templates
+     * @param limits
+     *            delimits the part of the text to be parsed for this template
+     * @param script
+     *            is the generator's configuration used to apply the new
+     *            template to model's objects
+     * @return the new template
+     * @throws TemplateSyntaxException
+     */
+    public static Template read(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        Template template = (Template) Template.readPreferred("read", buffer, limits, script); //$NON-NLS-1$
+        if (template == null) {
+            template = new Template(script);
+            template.setPos(limits);
+            if (buffer != null) {
+                final int[] pos = new int[4];
+                for (int i = 0; i < pos.length; i++) {
+                    pos[i] = -2;
+                }
+                int i = limits.b();
+                while (i < limits.e()) {
+                    if (pos[0] != -1 && i > pos[0]) {
+                        pos[0] = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.COMMENT_BEGIN, i, limits.e()).b();
+                    }
+                    if (pos[1] != -1 && i > pos[1]) {
+                        pos[1] = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_BEGIN, i, limits.e()).b();
+                    }
+                    if (pos[2] != -1 && i > pos[2]) {
+                        pos[2] = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.FOR_BEGIN, i, limits.e()).b();
+                    }
+                    if (pos[3] != -1 && i > pos[3]) {
+                        pos[3] = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.FEATURE_BEGIN, i, limits.e()).b();
+                    }
+                    final int iTab = Template.indexOfMin(pos);
+                    if (iTab == 0) {
+                        i = Template.readStatement(buffer, TemplateConstants.COMMENT_BEGIN, TemplateConstants.COMMENT_END, new Int2(i, limits.e()), template, script);
+                    } else if (iTab == 1) {
+                        i = Template.readStatement(buffer, TemplateConstants.IF_BEGIN, TemplateConstants.IF_END, new Int2(i, limits.e()), template, script);
+                    } else if (iTab == 2) {
+                        i = Template.readStatement(buffer, TemplateConstants.FOR_BEGIN, TemplateConstants.FOR_END, new Int2(i, limits.e()), template, script);
+                    } else if (iTab == 3) {
+                        i = Template.readStatement(buffer, TemplateConstants.FEATURE_BEGIN, TemplateConstants.FEATURE_END, new Int2(i, limits.e()), template, script);
+                    } else { // -1
+                        final Int2 posText = new Int2(i, limits.e());
+                        template.append(Template.readMiddleElement(buffer, posText, script));
+                        i = limits.e();
+                    }
+                }
+            }
+        }
+        return template;
+    }
+
+    /**
+     * It checks the syntax and creates a "middle" template element for the
+     * given part of the text. The part of the text to be parsed is delimited by
+     * the given limits. A middle template element is a textual representation
+     * that doesn't contain "<%...%>".
+     * 
+     * @param buffer
+     *            is the textual representation of the script that contains
+     *            templates
+     * @param limits
+     *            delimits the part of the text to be parsed for this "middle"
+     *            template element
+     * @param script
+     *            is the generator's configuration used to apply the new
+     *            template element to model's objects
+     * @return the new "middle" template element
+     * @throws TemplateSyntaxException
+     */
+    public static TemplateNodeElement readMiddleElement(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        TemplateNodeElement element = Template.readPreferred("readMiddleElement", buffer, limits, script); //$NON-NLS-1$
+        if (element == null) {
+            element = new TemplateText(buffer.substring(limits.b(), limits.e()), script);
+            element.setPos(limits);
+        }
+        return element;
+    }
+
+    /**
+     * It checks the syntax and creates a template element for the given part of
+     * the text. The part of the text to be parsed is delimited by the given
+     * limits. It tries to call a static method on the preferred template
+     * before. The static attribute 'preferredTemplate' has to be put before.
+     * 
+     * @param method
+     *            is the method name
+     * @param buffer
+     *            is the textual representation of the script that contains
+     *            templates
+     * @param limits
+     *            delimits the part of the text to be parsed
+     * @param script
+     *            is the generator's configuration used to apply the new
+     *            template element to model's objects
+     * @return the new template element
+     * @throws TemplateSyntaxException
+     */
+    private static TemplateNodeElement readPreferred(String method, String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        if (Template.preferredTemplate != Template.class) {
+            try {
+                return (TemplateNodeElement) Template.preferredTemplate.getMethod(method, new Class[] { String.class, Int2.class, IScript.class }).invoke(Template.preferredTemplate,
+                        new Object[] { buffer, limits, script });
+            } catch (final IllegalArgumentException e) {
+                AcceleoEcoreGenPlugin.getDefault().log(e, true);
+            } catch (final SecurityException e) {
+                AcceleoEcoreGenPlugin.getDefault().log(e, true);
+            } catch (final IllegalAccessException e) {
+                AcceleoEcoreGenPlugin.getDefault().log(e, true);
+            } catch (final InvocationTargetException e) {
+                if (e.getTargetException() instanceof TemplateSyntaxException) {
+                    throw (TemplateSyntaxException) e.getTargetException();
+                } else {
+                    AcceleoEcoreGenPlugin.getDefault().log(e, true);
+                }
+            } catch (final NoSuchMethodException e) {
+                AcceleoEcoreGenPlugin.getDefault().log(e, true);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * The preferred template is the class to use to create the templates in the
+     * sub statements.
+     */
+    protected static Class preferredTemplate = Template.class;
+
+    /**
+     * Gets the index of the minimum integer in the given table.
+     * 
+     * @param pos
+     *            is the table
+     * @return the index of the minimum integer
+     */
+    protected static int indexOfMin(int[] pos) {
+        int index = -1;
+        int min = Integer.MAX_VALUE;
+        for (int i = 0; i < pos.length; i++) {
+            if (pos[i] > -1 && pos[i] < min) {
+                index = i;
+                min = pos[i];
+            }
+        }
+        return index;
+    }
+
+    /**
+     * Reads the statements in the buffer, starting at a specified position, and
+     * returns the ending index.
+     * 
+     * @param buffer
+     *            is the textual representation of the script that contains
+     *            templates
+     * @param tagBegin
+     *            is the begin tag of the statement
+     * @param tagEnd
+     *            is the end tag of the statement
+     * @param limits
+     *            delimits the part of the text to be parsed
+     * @param template
+     *            is the current template
+     * @param script
+     *            is the generator's configuration used to apply the new
+     *            statement to model's objects
+     * @return the ending index, or -1
+     * @throws TemplateSyntaxException
+     */
+    protected static int readStatement(String buffer, String tagBegin, String tagEnd, Int2 limits, Template template, IScript script) throws TemplateSyntaxException {
+        Int2 end = Int2.NOT_FOUND;
+        final Int2 begin = TextSearch.getDefaultSearch().indexIn(buffer, tagBegin, limits.b(), limits.e());
+        // ASSERT (begin.b > -1)
+        if (tagBegin == TemplateConstants.COMMENT_BEGIN) {
+            end = TextSearch.getDefaultSearch().blockIndexEndIn(buffer, tagBegin, tagEnd, begin.b(), limits.e(), false);
+        } else {
+            end = TextSearch.getDefaultSearch().blockIndexEndIn(buffer, tagBegin, tagEnd, begin.b(), limits.e(), true, null, TemplateConstants.INHIBS_STATEMENT);
+        }
+        if (end.b() > -1) {
+            final boolean untab = tagBegin != TemplateConstants.FEATURE_BEGIN && Template.isFirstSignificantOfLine(buffer, begin.b()) && Template.isLastSignificantOfLine(buffer, end.e());
+            if (begin.b() > limits.b()) {
+                int iEndText = begin.b();
+                if (untab) {
+                    // Delete (\s|\t)* before <%if..., <%for...
+                    int iPrevLine = TextSearch.getDefaultSearch().lastIndexIn(buffer, "\n", limits.b(), begin.b()).e(); //$NON-NLS-1$
+                    if (iPrevLine == -1) {
+                        iPrevLine = limits.b();
+                    }
+                    if (buffer.substring(iPrevLine, begin.b()).trim().length() == 0) {
+                        iEndText = iPrevLine;
+                    }
+                }
+                final Int2 posText = new Int2(limits.b(), iEndText);
+                template.append(Template.readMiddleElement(buffer, posText, script));
+            }
+            if (tagBegin == TemplateConstants.IF_BEGIN) {
+                template.append(TemplateIfStatement.fromString(buffer, new Int2(begin.e(), end.b()), script));
+            }
+            if (tagBegin == TemplateConstants.FOR_BEGIN) {
+                template.append(TemplateForStatement.fromString(buffer, new Int2(begin.e(), end.b()), script));
+            }
+            if (tagBegin == TemplateConstants.FEATURE_BEGIN) {
+                template.append(TemplateFeatureStatement.fromString(buffer, new Int2(begin.e(), end.b()), script));
+            }
+            if (tagBegin == TemplateConstants.COMMENT_BEGIN) {
+                template.append(TemplateCommentStatement.fromString(buffer, new Int2(begin.e(), end.b()), script));
+            }
+            if (untab) {
+                // Delete (\s|\t)*\n after <%}%>
+                int iNextLine = TextSearch.getDefaultSearch().indexIn(buffer, "\n", end.e(), limits.e()).e(); //$NON-NLS-1$
+                if (iNextLine == -1) {
+                    iNextLine = limits.e();
+                }
+                if (buffer.substring(end.e(), iNextLine).trim().length() == 0) {
+                    return iNextLine;
+                }
+            }
+            return end.e();
+        } else {
+            template.append(Template.readMiddleElement(buffer, limits, script));
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("Template.UnclosedTag", new Object[] { tagEnd, tagBegin, }), script, new Int2(begin.b(), limits.e())); //$NON-NLS-1$
+        }
+    }
+
+    private static boolean isFirstSignificantOfLine(String buffer, int index) {
+        if (index > 0 && index < buffer.length()) {
+            index--;
+            while (index >= 0) {
+                final char c = buffer.charAt(index);
+                if (c == '\n') {
+                    return true;
+                } else if (c == ' ' || c == '\t' || c == '\r') {
+                    index--;
+                } else {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static boolean isLastSignificantOfLine(String buffer, int index) {
+        if (index >= 0) {
+            while (index < buffer.length()) {
+                final char c = buffer.charAt(index);
+                if (c == '\n') {
+                    return true;
+                } else if (c == ' ' || c == '\t' || c == '\r') {
+                    index++;
+                } else {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Formats the text of a template in a script.
+     * 
+     * @param buffer
+     *            is the full text of a script
+     * @param limits
+     *            delimits the part of the text to parse for this template
+     * @param nbReturn
+     *            is the number of return character to ignore at the end of the
+     *            template
+     * @return is the new limits that delimits the part of the text to parse for
+     *         this template
+     */
+    public static Int2 formatTemplate(String buffer, Int2 limits, int nbReturn) {
+        if (limits.b() == -1 || limits.b() > limits.e()) {
+            return Int2.NOT_FOUND;
+        }
+        final String text = buffer.substring(limits.b(), limits.e());
+        // Search first valid char
+        int posBegin = text.indexOf("\n"); //$NON-NLS-1$
+        if (posBegin == -1 || text.substring(0, posBegin).trim().length() > 0) {
+            posBegin = 0;
+        } else {
+            posBegin++;
+        }
+        // Search last valid char
+        if (text.length() > 0) {
+            int n = 0;
+            int endLine = text.length();
+            int posEnd = text.length() - 1;
+            boolean stop = false;
+            while (!stop) {
+                final char c = text.charAt(posEnd);
+                if (nbReturn == 0 && c == '\n') {
+                    posEnd++;
+                    stop = true;
+                } else if (c == '\n' && n < nbReturn) {
+                    n++;
+                    endLine = posEnd;
+                } else if (c == '\r') {
+                    endLine = posEnd;
+                } else if (c == ' ' || c == '\t') {
+                } else {
+                    // Keep space at end
+                    posEnd = endLine;
+                    stop = true;
+                }
+                if (!stop) {
+                    if (posEnd > posBegin) {
+                        posEnd--;
+                    } else {
+                        if (nbReturn != 0) {
+                            posEnd = endLine;
+                        }
+                        stop = true;
+                    }
+                }
+            }
+            if (posEnd >= posBegin) {
+                boolean formatWithComment = false;
+                String sub = text.substring(posBegin, posEnd);
+                if (sub.startsWith(TemplateConstants.COMMENT_BEGIN) && sub.indexOf(TemplateConstants.COMMENT_END) > -1) {
+                    posBegin = text.indexOf(TemplateConstants.COMMENT_END, posBegin) + TemplateConstants.COMMENT_END.length();
+                    formatWithComment = true;
+                    if (posEnd > posBegin) {
+                        sub = sub.substring(posBegin);
+                    } else {
+                        sub = ""; //$NON-NLS-1$
+                    }
+                }
+                if (sub.endsWith(TemplateConstants.COMMENT_END) && sub.lastIndexOf(TemplateConstants.COMMENT_BEGIN, posEnd) > -1) {
+                    posEnd = text.lastIndexOf(TemplateConstants.COMMENT_BEGIN, posEnd);
+                    formatWithComment = true;
+                }
+                if (formatWithComment) {
+                    return Template.formatTemplate(buffer, new Int2(limits.b() + posBegin, limits.b() + posEnd), nbReturn);
+                } else {
+                    return new Int2(limits.b() + posBegin, limits.b() + posEnd);
+                }
+            }
+        }
+        return limits;
+    }
+
+    /**
+     * Evaluates this template on an EObject, and converts the result to a
+     * string.
+     * 
+     * @param object
+     *            is the model's object
+     * @param mode
+     *            is the mode in which to launch, one of the mode constants
+     *            defined - RUN_MODE or DEBUG_MODE
+     * @return the textual representation of the EObject for this template
+     * @throws ENodeException
+     * @throws FactoryException
+     */
+    public String evaluateAsString(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        final String text = evaluate(object, mode).asString();
+        return text;
+    }
+
+    /**
+     * Evaluates this template on an EObject. The result node of generation is
+     * an ENode. The given comment is generated before the object if it isn't
+     * null or empty.
+     * 
+     * @param object
+     *            is the model's object
+     * @param comment
+     *            that is generated before the object if it isn't null or empty
+     * @param mode
+     *            is the mode in which to launch, one of the mode constants
+     *            defined - RUN_MODE or DEBUG_MODE
+     * @return the result node of generation
+     * @throws ENodeException
+     * @throws FactoryException
+     * @see ENode
+     */
+    public ENode evaluateWithComment(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        final ENode node = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+        String comment = eGetAsString(object, "comment"); //$NON-NLS-1$
+        if (comment.length() > 0) {
+            node.append(comment, TextModelMapping.HIGHLIGHTED_COMMENT);
+        }
+        node.append(evaluate(object, mode));
+        comment = eGetAsString(object, "endLineComment"); //$NON-NLS-1$
+        if (comment.length() > 0) {
+            node.append(comment, TextModelMapping.HIGHLIGHTED_COMMENT);
+        }
+        return node;
+    }
+
+    private String eGetAsString(EObject object, String feature) {
+        try {
+            String result = EFactory.eGetAsString(object, feature);
+            if (result == null) {
+                result = ""; //$NON-NLS-1$
+            }
+            return result;
+        } catch (final FactoryException e) {
+            return ""; //$NON-NLS-1$
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        if (mode.getMonitor() != null && mode.getMonitor().isCanceled()) {
+            throw new OperationCanceledException();
+        }
+
+        ENode node = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+        boolean parentIsStatement = getParent() instanceof TemplateForStatement || getParent() instanceof TemplateIfStatement;
+        if (!parentIsStatement && currentEval.contains(object)) {
+            emptyEvaluation = true;
+            throw new ENodeException(AcceleoGenMessages.getString("Template.RecursiveCall", new Object[] { toString(), }), pos, script, object, true); //$NON-NLS-1$
+        } else {
+            if (script != null) {
+                final ENode tmp = new ENode(object, this, mode.isSynchronize());
+                script.contextPush(IScript.CURRENT_NODE, tmp);
+                script.contextPush(IScript.TEMPLATE_NODE, tmp);
+            }
+            try {
+                if (!parentIsStatement) {
+                    currentEval.add(object);
+                }
+                TemplateNodeElement precedingElement = null;
+                ENode precedingChild = null;
+                final Iterator elements = this.elements.iterator();
+                while (elements.hasNext()) {
+                    final TemplateNodeElement element = (TemplateNodeElement) elements.next();
+                    try {
+                        if (!elements.hasNext() && element instanceof TemplateText && (node.isEObject() || node.isList() && node.getList().size() > 0 && node.getList().get(0).isEObject())
+                                && ((TemplateText) element).getText().trim().length() == 0) {
+                            break;
+                        }
+                    } catch (final ENodeCastException e) {
+                        // never catch
+                    }
+                    final ENode child = element.evaluate(object, mode);
+                    try {
+                        if (element.getScript() != null && element.getScript().getFile() != null && element.getScript().getFile().getName().endsWith(".mt") //$NON-NLS-1$
+                                && element instanceof TemplateFeatureStatement && precedingElement instanceof TemplateText && precedingChild.isString() && precedingChild.getString().length() > 0) {
+                            final String text = child.asString();
+                            if (text.indexOf("\n") > -1) { //$NON-NLS-1$
+                                final String precedingText = precedingChild.getString();
+                                final int iLine = precedingText.lastIndexOf("\n"); //$NON-NLS-1$
+                                if (iLine > -1 && iLine + 1 < precedingText.length()) {
+                                    final String indent = precedingText.substring(iLine + 1);
+                                    if (indent.trim().length() == 0) {
+                                        child.stringCall("internalIndent:" + indent, 0, 0); //$NON-NLS-1$
+                                    }
+                                }
+                            }
+                        }
+                    } catch (final ENodeCastException e) {
+                        // never catch
+                    }
+                    node.append(child);
+                    precedingElement = element;
+                    precedingChild = child;
+                }
+            } finally {
+                if (script != null) {
+                    script.contextPop(IScript.CURRENT_NODE);
+                    script.contextPop(IScript.TEMPLATE_NODE);
+                }
+                if (!parentIsStatement) {
+                    currentEval.remove(object);
+                }
+            }
+        }
+        if (postExpression != null) {
+            node = postExpression.evaluate(node, script, mode);
+        }
+        emptyEvaluation = node.size() == 0;
+        return node;
+    }
+
+    /**
+     * The current evaluations.
+     */
+    protected List currentEval = new ArrayList();
+
+    /**
+     * Tells whether or not this template contains the given text, ignoring case
+     * or not.
+     * 
+     * @param text
+     *            is the string to be searched
+     * @param ignoreCase
+     *            indicates if case differences have been eliminated
+     * @return true if template contains the given text
+     */
+    public boolean containsText(String text, boolean ignoreCase) {
+        if (ignoreCase) {
+            return toString().toUpperCase().indexOf(text.toUpperCase()) > -1;
+        } else {
+            return toString().indexOf(text) > -1;
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public int hashCode() {
+        if (pos.b() >= 1) {
+            return pos.b();
+        } else {
+            return super.hashCode();
+        }
+    }
+
+    /**
+     * Gets the significant statements of this template : it ignores comment and
+     * simple text.
+     * 
+     * @return the significant statements of this template.
+     */
+    public List getSignificantStatements() {
+        final List result = new ArrayList();
+        final Iterator it = children.iterator();
+        while (it.hasNext()) {
+            final TemplateElement element = (TemplateElement) it.next();
+            if (element instanceof TemplateNodeElement && !(element instanceof TemplateCommentStatement) && !(element instanceof TemplateText)) {
+                result.add(element);
+            }
+        }
+        return result;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateConstants.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateConstants.java
new file mode 100644
index 0000000..085e8de
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateConstants.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template;
+
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * Constants for the generation tool.
+ * 
+ * 
+ */
+public class TemplateConstants {
+
+    // Template's global constants.
+
+    public static String SPEC;
+
+    // Template's comments.
+
+    public static String COMMENT_BEGIN;
+
+    public static String COMMENT_END;
+
+    public static String[] COMMENT;
+
+    public static String[][] INHIBS_COMMENT;
+
+    // Template's imports.
+
+    public static String IMPORT_BEGIN;
+
+    public static String IMPORT_END;
+
+    public static String IMPORT_WORD;
+
+    public static String MODELTYPE_WORD;
+
+    // Template's user code.
+
+    public static String USER_BEGIN_NAME;
+
+    public static String USER_BEGIN;
+
+    public static String USER_END_NAME;
+
+    public static String USER_END;
+
+    // Template's expressions.
+
+    public static String[] PARENTH;
+
+    public static String[] BRACKETS;
+
+    public static String[] LITERAL;
+
+    public static String LITERAL_SPEC;
+
+    public static String[][] INHIBS_EXPRESSION;
+
+    public static String NOT;
+
+    public static String OPERATOR_OR;
+
+    public static String OPERATOR_AND;
+
+    public static String OPERATOR_EQUALS;
+
+    public static String OPERATOR_NOT_EQUALS;
+
+    public static String OPERATOR_SUP_EQUALS;
+
+    public static String OPERATOR_INF_EQUALS;
+
+    public static String OPERATOR_SUP;
+
+    public static String OPERATOR_INF;
+
+    public static String OPERATOR_ADD;
+
+    public static String OPERATOR_SUB;
+
+    public static String OPERATOR_DIV;
+
+    public static String OPERATOR_MUL;
+
+    public static String[] OPERATORS;
+
+    public static String CALL_SEP;
+
+    public static String ARG_SEP;
+
+    // Template's statements.
+
+    public static String IF_BEGIN;
+
+    public static String IF_THEN;
+
+    public static String IF_ELSE;
+
+    public static String IF_ELSE_IF;
+
+    public static String IF_END;
+
+    public static String[] IF;
+
+    public static String FOR_BEGIN;
+
+    public static String FOR_THEN;
+
+    public static String FOR_END;
+
+    public static String[] FOR;
+
+    public static String FEATURE_BEGIN;
+
+    public static String FEATURE_END;
+
+    public static String[] FEATURE;
+
+    public static String[][] INHIBS_STATEMENT;
+
+    // Template's declaration line.
+
+    public static String SCRIPT_BEGIN;
+
+    public static String SCRIPT_TYPE;
+
+    public static String SCRIPT_NAME;
+
+    public static String SCRIPT_DESC;
+
+    public static String SCRIPT_FILE;
+
+    public static String SCRIPT_POST;
+
+    public static String SCRIPT_PROPERTY_ASSIGN;
+
+    public static String SCRIPT_END;
+
+    public static String[] SCRIPT_PROPERTIES_SEPARATORS;
+
+    public static String[][] INHIBS_SCRIPT_DECLA;
+
+    public static String[][] INHIBS_SCRIPT_CONTENT;
+
+    // Link prefix
+
+    public static String LINK_PREFIX_SCRIPT;
+
+    public static String LINK_PREFIX_METAMODEL;
+
+    public static String LINK_PREFIX_METAMODEL_SHORT;
+
+    public static String LINK_PREFIX_JAVA;
+
+    public static String LINK_PREFIX_SEPARATOR;
+
+    // Predefined links
+
+    public static String LINK_NAME_ARGS;
+
+    public static String LINK_NAME_INDEX;
+
+    public static String SERVICE_SEP;
+
+    public static String SERVICE_SEPSTR;
+
+    private static Character lastFirstChar = null;
+
+    /**
+     * Initializes all the constants for the generation tool.
+     */
+    public static void initConstants() {
+        TemplateConstants.initConstants(""); //$NON-NLS-1$
+    }
+
+    /**
+     * Initializes all the constants for the generation tool.
+     * 
+     * @param content
+     *            is the text that is used to determine the first and the last
+     *            character of the tags
+     */
+    public static void initConstants(String content) {
+        // Choose tag
+        if (content == null) {
+            content = ""; //$NON-NLS-1$
+        } else {
+            content = content.trim();
+        }
+        boolean tab = content.length() > 0 && content.charAt(0) == '[';
+        char first = (tab) ? '[' : '<';
+        if (TemplateConstants.lastFirstChar != null && first == TemplateConstants.lastFirstChar.charValue()) {
+            return;
+        } else {
+            TemplateConstants.lastFirstChar = new Character(first);
+        }
+        char last = (tab) ? ']' : '>';
+
+        // contains String equal to first + "%" and "%" + last, avoid too much
+        // concatenations later on
+        final String tagStart = Character.toString(first) + '%';
+        final String tagEnd = '%' + Character.toString(last);
+
+        // Update constants
+        TemplateConstants.SPEC = "\\\""; //$NON-NLS-1$
+        TemplateConstants.COMMENT_BEGIN = tagStart + "--"; //$NON-NLS-1$
+        TemplateConstants.COMMENT_END = "--" + tagEnd; //$NON-NLS-1$
+        TemplateConstants.COMMENT = new String[] { TemplateConstants.COMMENT_BEGIN, TemplateConstants.COMMENT_END, TextSearch.FORCE_NOT_RECURSIVE };
+        TemplateConstants.INHIBS_COMMENT = new String[][] { TemplateConstants.COMMENT };
+        TemplateConstants.IMPORT_BEGIN = tagStart;
+        TemplateConstants.IMPORT_END = tagEnd;
+        TemplateConstants.IMPORT_WORD = "import"; //$NON-NLS-1$
+        TemplateConstants.MODELTYPE_WORD = "metamodel"; //$NON-NLS-1$
+        TemplateConstants.USER_BEGIN_NAME = "startUserCode"; //$NON-NLS-1$
+        TemplateConstants.USER_BEGIN = tagStart + TemplateConstants.USER_BEGIN_NAME + tagEnd;
+        TemplateConstants.USER_END_NAME = "endUserCode"; //$NON-NLS-1$
+        TemplateConstants.USER_END = tagStart + TemplateConstants.USER_END_NAME + tagEnd;
+        TemplateConstants.PARENTH = new String[] { "(", ")" }; //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateConstants.BRACKETS = new String[] { "[", "]" }; //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateConstants.LITERAL = new String[] { "\"", "\"", TextSearch.FORCE_NOT_RECURSIVE }; //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateConstants.LITERAL_SPEC = "\\\""; //$NON-NLS-1$
+        TemplateConstants.INHIBS_EXPRESSION = new String[][] { TemplateConstants.PARENTH, TemplateConstants.LITERAL, TemplateConstants.BRACKETS };
+        TemplateConstants.NOT = "!"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_OR = "||"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_AND = "&&"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_EQUALS = "=="; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_NOT_EQUALS = "!="; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_SUP_EQUALS = ">="; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_INF_EQUALS = "<="; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_SUP = ">"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_INF = "<"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_ADD = "+"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_SUB = "-"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_DIV = "/"; //$NON-NLS-1$
+        TemplateConstants.OPERATOR_MUL = "*"; //$NON-NLS-1$
+        TemplateConstants.OPERATORS = new String[] { TemplateConstants.OPERATOR_OR, TemplateConstants.OPERATOR_AND, TemplateConstants.OPERATOR_EQUALS, TemplateConstants.OPERATOR_NOT_EQUALS,
+                TemplateConstants.OPERATOR_SUP_EQUALS, TemplateConstants.OPERATOR_INF_EQUALS, TemplateConstants.OPERATOR_SUP, TemplateConstants.OPERATOR_INF, TemplateConstants.OPERATOR_ADD,
+                TemplateConstants.OPERATOR_SUB, TemplateConstants.OPERATOR_DIV, TemplateConstants.OPERATOR_MUL };
+        TemplateConstants.CALL_SEP = "."; //$NON-NLS-1$
+        TemplateConstants.ARG_SEP = ","; //$NON-NLS-1$
+        TemplateConstants.IF_BEGIN = tagStart + "if "; //$NON-NLS-1$
+        TemplateConstants.IF_THEN = '{' + tagEnd;
+        TemplateConstants.IF_ELSE = tagStart + "}else{" + tagEnd; //$NON-NLS-1$
+        TemplateConstants.IF_ELSE_IF = tagStart + "}else if"; //$NON-NLS-1$
+        TemplateConstants.IF_END = tagStart + '}' + tagEnd;
+        TemplateConstants.IF = new String[] { TemplateConstants.IF_BEGIN, TemplateConstants.IF_END };
+        TemplateConstants.FOR_BEGIN = tagStart + "for "; //$NON-NLS-1$
+        TemplateConstants.FOR_THEN = '{' + tagEnd;
+        TemplateConstants.FOR_END = tagStart + '}' + tagEnd;
+        TemplateConstants.FOR = new String[] { TemplateConstants.FOR_BEGIN, TemplateConstants.FOR_END };
+        TemplateConstants.FEATURE_BEGIN = tagStart;
+        TemplateConstants.FEATURE_END = tagEnd;
+        TemplateConstants.FEATURE = new String[] { TemplateConstants.FEATURE_BEGIN, TemplateConstants.FEATURE_END };
+        TemplateConstants.INHIBS_STATEMENT = new String[][] { TemplateConstants.COMMENT, TemplateConstants.IF, TemplateConstants.FOR, TemplateConstants.FEATURE, };
+        TemplateConstants.SCRIPT_BEGIN = tagStart + "script "; //$NON-NLS-1$
+        TemplateConstants.SCRIPT_TYPE = "type"; //$NON-NLS-1$
+        TemplateConstants.SCRIPT_NAME = "name"; //$NON-NLS-1$
+        TemplateConstants.SCRIPT_DESC = "description"; //$NON-NLS-1$
+        TemplateConstants.SCRIPT_FILE = "file"; //$NON-NLS-1$
+        TemplateConstants.SCRIPT_POST = "post"; //$NON-NLS-1$
+        TemplateConstants.SCRIPT_PROPERTY_ASSIGN = "="; //$NON-NLS-1$
+        TemplateConstants.SCRIPT_END = tagEnd;
+        TemplateConstants.SCRIPT_PROPERTIES_SEPARATORS = new String[] { TemplateConstants.SCRIPT_PROPERTY_ASSIGN, " ", "\t", "\r", "\n" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        TemplateConstants.INHIBS_SCRIPT_DECLA = new String[][] { TemplateConstants.LITERAL };
+        TemplateConstants.INHIBS_SCRIPT_CONTENT = new String[][] { TemplateConstants.COMMENT, TemplateConstants.FEATURE };
+        TemplateConstants.LINK_PREFIX_SCRIPT = "script"; //$NON-NLS-1$
+        TemplateConstants.LINK_PREFIX_METAMODEL = "metamodel"; //$NON-NLS-1$
+        TemplateConstants.LINK_PREFIX_METAMODEL_SHORT = "m"; //$NON-NLS-1$
+        TemplateConstants.LINK_PREFIX_JAVA = "service"; //$NON-NLS-1$
+        TemplateConstants.LINK_PREFIX_SEPARATOR = "::"; //$NON-NLS-1$
+        TemplateConstants.LINK_NAME_ARGS = "args"; //$NON-NLS-1$
+        TemplateConstants.LINK_NAME_INDEX = "i"; //$NON-NLS-1$
+        TemplateConstants.SERVICE_SEP = "sep"; //$NON-NLS-1$
+        TemplateConstants.SERVICE_SEPSTR = "sepStr"; //$NON-NLS-1$
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateElement.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateElement.java
new file mode 100644
index 0000000..98ca165
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateElement.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * This is a template's element for the generation tool.
+ * 
+ * 
+ */
+public abstract class TemplateElement {
+
+    /**
+     * The script.
+     */
+    protected IScript script;
+
+    /**
+     * The parent element.
+     */
+    protected TemplateElement parent = null;
+
+    /**
+     * The children.
+     */
+    protected List children = new ArrayList();
+
+    /**
+     * The next element.
+     */
+    protected TemplateElement next = null;
+
+    /**
+     * The previous element.
+     */
+    protected TemplateElement previous = null;
+
+    /**
+     * The position in the script file.
+     */
+    protected Int2 pos = Int2.NOT_FOUND;
+
+    /**
+     * The line in the script file.
+     */
+    protected Integer line = null;
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public TemplateElement(IScript script) {
+        this.script = script;
+    }
+
+    /**
+     * @return the script
+     */
+    public IScript getScript() {
+        return script;
+    }
+
+    /**
+     * @return the position of this expression
+     */
+    public Int2 getPos() {
+        return this.pos;
+    }
+
+    /**
+     * @param pos
+     *            is the position of this expression
+     */
+    public void setPos(Int2 pos) {
+        this.pos = pos;
+        line = null;
+    }
+
+    /**
+     * @return the line of this expression
+     */
+    public int getLine() {
+        if (line == null) {
+            if (pos.b() == -1 || getScript() == null || getScript().getFile() == null) {
+                line = new Integer(0);
+            } else {
+                line = new Integer(TextSearch.getDefaultSearch().lineNumber(getScript().getFile(), pos.b()));
+            }
+        }
+        return line.intValue();
+    }
+
+    /**
+     * Sets the parent element. This element is a child for the parent.
+     * 
+     * @param parent
+     *            is the parent element
+     */
+    public void setParent(TemplateElement parent) {
+        // ASSERT this.parent == null
+        this.parent = parent;
+        if (parent != null) {
+            if (parent.children.size() > 0) {
+                final TemplateElement previous = (TemplateElement) parent.children.get(parent.children.size() - 1);
+                this.previous = previous;
+                previous.next = this;
+            }
+            parent.children.add(this);
+        }
+    }
+
+    /**
+     * @return the parent element
+     */
+    public TemplateElement getParent() {
+        return parent;
+    }
+
+    /**
+     * @return the previous element
+     */
+    public TemplateElement getPrevious() {
+        return previous;
+    }
+
+    /**
+     * @return the next element
+     */
+    public TemplateElement getNext() {
+        return next;
+    }
+
+    /**
+     * Returns a table of children.
+     * 
+     * @return a table of children
+     */
+    public TemplateElement[] getChildren() {
+        return (TemplateElement[]) children.toArray(new TemplateElement[children.size()]);
+    }
+
+    /**
+     * Returns a table of the children that are instance of the given class.
+     * 
+     * @param c
+     *            is a class
+     * @return a table of the children that are instance of the given class
+     */
+    public TemplateElement[] getChildren(Class c) {
+        final List result = new ArrayList();
+        final Iterator it = children.iterator();
+        while (it.hasNext()) {
+            final TemplateElement element = (TemplateElement) it.next();
+            if (c.isInstance(element)) {
+                result.add(element);
+            }
+        }
+        return (TemplateElement[]) result.toArray(new TemplateElement[result.size()]);
+    }
+
+    /**
+     * Returns a table of the children and the gateway children that are
+     * instance of the given classes.
+     * 
+     * @param classes
+     *            are the kept children
+     * @param gatewayClasses
+     *            are the gateway nodes that aren't kept, but their children are
+     *            tested
+     * @return a table of the children that are instance of the given classes
+     */
+    public TemplateElement[] getChildren(Class[] classes, Class[] gatewayClasses) {
+        final List result = new ArrayList();
+        final Iterator it = children.iterator();
+        while (it.hasNext()) {
+            final TemplateElement element = (TemplateElement) it.next();
+            boolean instance = false;
+            for (int i = 0; i < gatewayClasses.length && !instance; i++) {
+                final Class c = gatewayClasses[i];
+                if (c.isInstance(element)) {
+                    result.addAll(Arrays.asList(element.getChildren(classes, gatewayClasses)));
+                    instance = true;
+                }
+            }
+            for (int i = 0; i < classes.length && !instance; i++) {
+                final Class c = classes[i];
+                if (c.isInstance(element)) {
+                    result.add(element);
+                    instance = true;
+                }
+            }
+        }
+        return (TemplateElement[]) result.toArray(new TemplateElement[result.size()]);
+    }
+
+    /**
+     * Returns a list of all the children that are instance of the given class.
+     * The result contains also the children of the children...
+     * 
+     * @param c
+     *            is a class
+     * @return a list of all the children that are instance of the given class
+     */
+    public List getAllElements(Class c) {
+        final List result = new ArrayList();
+        if (c.isInstance(this)) {
+            result.add(this);
+        }
+        final Iterator it = children.iterator();
+        while (it.hasNext()) {
+            final TemplateElement element = (TemplateElement) it.next();
+            result.addAll(element.getAllElements(c));
+        }
+        return result;
+    }
+
+    /**
+     * Returns the URI fragment of this template element.
+     * 
+     * @return the URI fragment of this template element
+     */
+    public String getURIFragment() {
+        final StringBuffer fragment = new StringBuffer(""); //$NON-NLS-1$
+        if (script != null && script.getFile() != null) {
+            fragment.append(Resources.encodeAcceleoAbsolutePath(script.getFile().getAbsolutePath()));
+        }
+        fragment.append(" //pos="); //$NON-NLS-1$
+        fragment.append(pos.b());
+        fragment.append(',');
+        fragment.append(pos.e());
+        return fragment.toString();
+    }
+
+    /**
+     * Gets the file that corresponds to the given fragment.
+     * 
+     * @param uriFragment
+     *            is the URI of the template element
+     * @return the file, or null if it doesn't exist
+     */
+    public static File getTemplateFileFromURIFragment(String uriFragment) {
+        if (uriFragment != null) {
+            String path;
+            final int i = uriFragment.indexOf(" //pos="); //$NON-NLS-1$
+            if (i > -1) {
+                path = uriFragment.substring(0, i).trim();
+            } else {
+                path = uriFragment;
+            }
+            final File file = new File(Resources.decodeAcceleoAbsolutePath(path));
+            if (file.exists()) {
+                return file;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets the position that corresponds to the given fragment.
+     * 
+     * @param uriFragment
+     *            is the URI of the template element
+     * @return the position in the template file, or Int2.NotFound if it doesn't
+     *         exist
+     */
+    public static Int2 getPositionFromURIFragment(String uriFragment) {
+        if (uriFragment != null) {
+            final String search = " //pos="; //$NON-NLS-1$
+            int i = uriFragment.indexOf(search);
+            if (i > -1) {
+                final String pos = uriFragment.substring(i + search.length()).trim();
+                i = pos.indexOf(","); //$NON-NLS-1$
+                if (i > -1) {
+                    final String b = pos.substring(0, i).trim();
+                    final String e = pos.substring(i + 1).trim();
+                    return new Int2(Integer.parseInt(b), Integer.parseInt(e));
+                }
+            }
+        }
+        return Int2.NOT_FOUND;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateNodeElement.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateNodeElement.java
new file mode 100644
index 0000000..1683cc5
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateNodeElement.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+
+/**
+ * This is a template's node element for the generation tool. This element can
+ * be applied to model's objects to allow dynamic generation.
+ * 
+ * 
+ */
+public abstract class TemplateNodeElement extends TemplateElement {
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public TemplateNodeElement(IScript script) {
+        super(script);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public abstract String toString();
+
+    /**
+     * Evaluates this template element on an EObject. The result node of
+     * generation is an ENode.
+     * 
+     * @param object
+     *            is the model's object
+     * @param mode
+     *            is the mode in which to launch, one of the mode constants
+     *            defined - RUN_MODE or DEBUG_MODE
+     * @return the result node of generation
+     * @throws ENodeException
+     * @throws FactoryException
+     * @see ENode
+     */
+    public abstract ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException;
+
+    /**
+     * Returns the text to put in an outline view.
+     * 
+     * @return the text to put in an outline view
+     */
+    public abstract String getOutlineText();
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateSyntaxException.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateSyntaxException.java
new file mode 100644
index 0000000..97936f2
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateSyntaxException.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template;
+
+import org.eclipse.core.resources.IMarker;
+
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.log.AcceleoException;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * Template Syntax Exception.
+ * 
+ * 
+ */
+public class TemplateSyntaxException extends AcceleoException {
+
+    private static final long serialVersionUID = 1;
+
+    /**
+     * The script.
+     */
+    protected IScript script;
+
+    /**
+     * Position of the syntax error.
+     */
+    protected Int2 pos;
+
+    /**
+     * The severity of this exception. The default is IMarker.SEVERITY_ERROR.
+     */
+    private int severity = IMarker.SEVERITY_ERROR;
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     * @param script
+     *            is the script
+     * @param pos
+     *            is the position of the syntax error
+     */
+    public TemplateSyntaxException(String message, IScript script, Int2 pos) {
+        super(message);
+        this.script = script;
+        this.pos = pos;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     * @param script
+     *            is the script
+     * @param pos
+     *            is the position of the syntax error
+     */
+    public TemplateSyntaxException(String message, IScript script, int pos) {
+        super(message);
+        this.script = script;
+        this.pos = new Int2(pos, pos + 1);
+    }
+
+    /**
+     * @return the position of the syntax error
+     */
+    public Int2 getPos() {
+        return pos;
+    }
+
+    /**
+     * @return the script
+     */
+    public IScript getScript() {
+        return script;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getMessage() {
+        return super.getMessage();
+    }
+
+    /**
+     * Set the severity of this syntaxe exception. {@see IMarker}
+     * 
+     * @param severity
+     *            the severity
+     */
+    public void setSeverity(int severity) {
+        this.severity = severity;
+    }
+
+    /**
+     * Get the severity of this exception. {@see IMarker}
+     * 
+     * @return
+     */
+    public int getSeverity() {
+        return severity;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateSyntaxExceptions.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateSyntaxExceptions.java
new file mode 100644
index 0000000..d6f9718
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateSyntaxExceptions.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.tools.log.AcceleoException;
+
+/**
+ * List of template syntax exceptions.
+ * 
+ * 
+ */
+public class TemplateSyntaxExceptions extends AcceleoException {
+
+    private static final long serialVersionUID = 1;
+
+    /**
+     * List of problems (TemplateSyntaxException).
+     */
+    protected List problems;
+
+    /**
+     * Constructor.
+     */
+    public TemplateSyntaxExceptions(List problems) {
+        super();
+        this.problems = problems;
+    }
+
+    /**
+     * @return the list of problems
+     */
+    public List getProblems() {
+        return problems;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getMessage() {
+        StringBuffer report = new StringBuffer(""); //$NON-NLS-1$
+        Iterator it = problems.iterator();
+        while (it.hasNext()) {
+            TemplateSyntaxException e = (TemplateSyntaxException) it.next();
+            if (e.getScript() != null && e.getScript().getFile() != null) {
+                report.append(AcceleoGenMessages.getString("TemplateSyntaxExceptions.ErrorInFile", new Object[] { e.getScript().getFile().getAbsolutePath().toString(), })); //$NON-NLS-1$
+            } else {
+                report.append(AcceleoGenMessages.getString("TemplateSyntaxExceptions.ErrorUnknownFile")).append(':'); //$NON-NLS-1$
+            }
+            report.append('\n');
+            report.append(e.getMessage());
+            report.append('\n');
+        }
+        return report.toString();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateText.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateText.java
new file mode 100644
index 0000000..5ae9787
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/TemplateText.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.eval.TextModelMapping;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+
+/**
+ * This is an element for the generation tool, used to generate static text.
+ * 
+ * 
+ */
+public class TemplateText extends TemplateNodeElement {
+
+    /**
+     * Static text.
+     */
+    protected String text;
+
+    /**
+     * Constructor.
+     * 
+     * @param text
+     *            is the static text
+     * @param script
+     *            is the script
+     */
+    public TemplateText(String text, IScript script) {
+        super(script);
+        this.text = text;
+    }
+
+    /**
+     * @return the text
+     */
+    public String getText() {
+        return text;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return text;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getOutlineText() {
+        return toString();
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        ENode node = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+        node.append(text, TextModelMapping.HIGHLIGHTED_STATIC_TEXT);
+        return node;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENode.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENode.java
new file mode 100644
index 0000000..e638e81
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENode.java
@@ -0,0 +1,1255 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import java.text.NumberFormat;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.common.util.Enumerator;
+import org.eclipse.emf.ecore.EEnumLiteral;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.EcorePackage;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.EFactory;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateElement;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalLog;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * Node of generation. Result of a template evaluation.
+ * <p>
+ * Encapsulates a generation value :
+ * <li>EObject</li>
+ * <li>ENodeList</li>
+ * <li>String</li>
+ * <li>boolean</li>
+ * <li>int</li>
+ * <li>double</li>
+ * <li>null</li>
+ * 
+ * 
+ */
+public class ENode implements Comparable {
+
+    /**
+     * Value of this node.
+     * <p>
+     * It's an EObject, an ENodeList, a String, a Boolean, an Integer, or null.
+     */
+    protected Object value;
+
+    /**
+     * Type of this node.
+     * <p>
+     * <li>type == T_EObject : the value is an EObject</li>
+     * <li>type == T_ENodeList : the value is an ENodeList</li>
+     * <li>type == T_String : the value is a String</li>
+     * <li>type == T_boolean : the value is a Boolean</li>
+     * <li>type == T_int : the value is an Integer</li>
+     * <li>type == T_double : the value is a Double</li>
+     * <li>type == T_null : the value is null</li>
+     */
+    protected String type;
+
+    protected static final String T_EObject = "EObject"; //$NON-NLS-1$
+
+    protected static final String T_ENodeList = "ENodeList"; //$NON-NLS-1$
+
+    protected static final String T_String = "String"; //$NON-NLS-1$
+
+    protected static final String T_boolean = "boolean"; //$NON-NLS-1$
+
+    protected static final String T_int = "int"; //$NON-NLS-1$
+
+    protected static final String T_double = "double"; //$NON-NLS-1$
+
+    protected static final String T_null = "null"; //$NON-NLS-1$
+
+    /**
+     * Class of this node.
+     * <p>
+     * <li>type == T_EObject : the class is EObject.class</li>
+     * <li>type == T_ENodeList : the class is ENodeList.class</li>
+     * <li>type == T_String : the class is String.class</li>
+     * <li>type == T_boolean : the class is boolean.class</li>
+     * <li>type == T_int : the class is int.class</li>
+     * <li>type == T_double : the class is double.class</li>
+     * <li>type == T_null : the class is null</li>
+     */
+    protected Class typeClass;
+
+    /**
+     * It's the model element used to generate this node.
+     */
+    protected EObject containerEObject;
+
+    /**
+     * It's the template element used to generate this node.
+     */
+    protected TemplateElement containerTemplateElement;
+
+    /**
+     * Correspondences between the model and the text value, can be null.
+     */
+    protected TextModelMapping textModelMapping;
+
+    /**
+     * Correspondences between the template element and the text value, can be
+     * null.
+     */
+    protected TextTemplateElementMapping textTemplateElementMapping;
+
+    /**
+     * Evaluation errors and warnings.
+     */
+    protected EvalLog log = new EvalLog();
+
+    /**
+     * Activates model/text mapping.
+     */
+    private boolean synchronize = true;
+
+    /**
+     * @return the value of this node : an EObject, an ENodeList, a String, a
+     *         Boolean, an Integer, or null.
+     */
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * @return the type of this node : "EObject", "ENodeList", "String",
+     *         "boolean", "int", "double", or null.
+     */
+    public String getType() {
+        return type;
+    }
+
+    /**
+     * @return the class of this node : EObject.class, ENodeList.class,
+     *         String.class, boolean.class, int.class, double.class, or null.
+     */
+    public Class getTypeClass() {
+        return typeClass;
+    }
+
+    /**
+     * @return the model element used to generate this node
+     */
+    public EObject getContainerEObject() {
+        return containerEObject;
+    }
+
+    /**
+     * @return the template element used to generate this node
+     */
+    public TemplateElement getContainerTemplateElement() {
+        return containerTemplateElement;
+    }
+
+    /**
+     * @return correspondences between the model and the text value, can be null
+     */
+    public TextModelMapping getTextModelMapping() {
+        return textModelMapping;
+    }
+
+    /**
+     * @return correspondences between the template element and the text value,
+     *         can be null
+     */
+    public TextTemplateElementMapping getTextTemplateElementMapping() {
+        return textTemplateElementMapping;
+    }
+
+    /**
+     * @return evaluation errors and warnings
+     */
+    public EvalLog log() {
+        return log;
+    }
+
+    /**
+     * Creates a root node. The value is an EObject. The model element used to
+     * generate this node is the element itself because the parent node is
+     * unknown.
+     * <p>
+     * Precondition : object != EMPTY && object != null
+     * <p>
+     * Remark : eContainer() == getValue().
+     * 
+     * @param object
+     *            is the value
+     * @deprecated
+     */
+    @Deprecated
+    public ENode(EObject object) {
+        this(object, (TemplateElement) null, true);
+    }
+
+    /**
+     * Creates a root node. The value is an EObject. The model element used to
+     * generate this node is the element itself because the parent node is
+     * unknown.
+     * <p>
+     * Precondition : object != EMPTY && object != null
+     * <p>
+     * Remark : eContainer() == getValue().
+     * 
+     * @param object
+     *            is the value
+     * @param element
+     *            is the template element
+     * @param synchronize
+     *            activates model/text mapping
+     */
+    public ENode(EObject object, TemplateElement element, boolean synchronize) {
+        containerEObject = object;
+        containerTemplateElement = element;
+        this.synchronize = synchronize;
+        init(object, ENode.T_EObject, EObject.class);
+    }
+
+    /**
+     * Creates a child node. The value is an EObject. The model element used to
+     * generate this node is the same element as for the parent.
+     * <p>
+     * Remark : eContainer() == parent.eContainer().
+     * 
+     * @param object
+     *            is the value
+     * @param parent
+     *            is the parent node
+     */
+    public ENode(EObject object, ENode parent) {
+        init(parent);
+        init(object, ENode.T_EObject, EObject.class);
+    }
+
+    /**
+     * Creates a child node. The value is an EObject. The model element used to
+     * generate this node is the parent.
+     * <p>
+     * Precondition : parent != EMPTY && parent != null
+     * <p>
+     * Equivalent : new ENode(object, new ENode(parent)).
+     * 
+     * @param object
+     *            is the value
+     * @param parent
+     *            is the parent object
+     * @param element
+     *            is the template element
+     * @param synchronize
+     *            activates model/text mapping
+     */
+    public ENode(EObject object, EObject parent, TemplateElement element, boolean synchronize) {
+        this(object, new ENode(parent, element, synchronize));
+    }
+
+    /**
+     * Used to create empty ENode.
+     */
+    public static final EObject EMPTY = null;
+
+    /**
+     * Creates a child node. The value is an ENodeList. The model element used
+     * to generate this node is the same element as for the parent.
+     * <p>
+     * Remark : eContainer() == parent.eContainer().
+     * 
+     * @param l
+     *            is the value
+     * @param parent
+     *            is the parent node
+     */
+    public ENode(ENodeList l, ENode parent) {
+        init(parent);
+        init(l, ENode.T_ENodeList, ENodeList.class);
+    }
+
+    /**
+     * Creates a child node. The value is a String. The model element used to
+     * generate this node is the same element as for the parent.
+     * <p>
+     * Remark : eContainer() == parent.eContainer().
+     * 
+     * @param s
+     *            is the value
+     * @param parent
+     *            is the parent node
+     */
+    public ENode(String s, ENode parent) {
+        init(parent);
+        init(s, ENode.T_String, String.class);
+    }
+
+    /**
+     * Creates a child node. The value is a boolean. The model element used to
+     * generate this node is the same element as for the parent.
+     * <p>
+     * Remark : eContainer() == parent.eContainer().
+     * 
+     * @param b
+     *            is the value
+     * @param parent
+     *            is the parent node
+     */
+    public ENode(boolean b, ENode parent) {
+        init(parent);
+        init(new Boolean(b), ENode.T_boolean, boolean.class);
+    }
+
+    /**
+     * Creates a child node. The value is an int. The model element used to
+     * generate this node is the same element as for the parent.
+     * <p>
+     * Remark : eContainer() == parent.eContainer().
+     * 
+     * @param i
+     *            is the value
+     * @param parent
+     *            is the parent node
+     */
+    public ENode(int i, ENode parent) {
+        init(parent);
+        init(new Integer(i), ENode.T_int, int.class);
+    }
+
+    /**
+     * Creates a child node. The value is a double. The model element used to
+     * generate this node is the same element as for the parent.
+     * <p>
+     * Remark : eContainer() == parent.eContainer().
+     * 
+     * @param i
+     *            is the value
+     * @param parent
+     *            is the parent node
+     */
+    public ENode(double i, ENode parent) {
+        init(parent);
+        init(new Double(i), ENode.T_double, double.class);
+    }
+
+    /**
+     * Updates container and log.
+     * 
+     * @param parent
+     *            is the parent node
+     */
+    protected void init(ENode parent) {
+        if (parent != null) {
+            synchronize = parent.synchronize;
+            containerEObject = parent.containerEObject;
+            containerTemplateElement = parent.containerTemplateElement;
+            log.getAll(parent.log, false);
+        }
+    }
+
+    /**
+     * Updates value, type, and class.
+     * 
+     * @param value
+     *            is the value
+     * @param type
+     *            is the type of the value
+     * @param typeClass
+     *            is the class of the value
+     */
+    protected void init(Object value, String type, Class typeClass) {
+        if (value != null) {
+            this.value = value;
+            this.type = type;
+            this.typeClass = typeClass;
+        } else {
+            this.value = null;
+            this.type = ENode.T_null;
+            this.typeClass = null;
+        }
+        this.textModelMapping = createTextModelMapping();
+        this.textTemplateElementMapping = createTextTemplateElementMapping();
+    }
+
+    /**
+     * Updates text-model mapping, for String only.
+     * 
+     * @return a new mapping if the value is a String, null if not
+     */
+    protected TextModelMapping createTextModelMapping() {
+        if (isString() && containerEObject != null) {
+            TextModelMapping mapping = new TextModelMapping(containerEObject, !synchronize);
+            mapping.shift(((String) value).length());
+            return mapping;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Updates text-template mapping, for String only.
+     * 
+     * @return a new mapping
+     */
+    protected TextTemplateElementMapping createTextTemplateElementMapping() {
+        if (isString() && containerTemplateElement != null) {
+            TextTemplateElementMapping mapping = new TextTemplateElementMapping(containerTemplateElement, !synchronize);
+            mapping.shift(((String) value).length());
+            return mapping;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @return true if it's an EObject, false if not
+     */
+    public boolean isEObject() {
+        return type == ENode.T_EObject;
+    }
+
+    /**
+     * @return true if it's an ENodeList, false if not
+     */
+    public boolean isList() {
+        return type == ENode.T_ENodeList;
+    }
+
+    /**
+     * @return true if it's a String, false if not
+     */
+    public boolean isString() {
+        return type == ENode.T_String;
+    }
+
+    /**
+     * @return true if it's a boolean, false if not
+     */
+    public boolean isBoolean() {
+        return type == ENode.T_boolean;
+    }
+
+    /**
+     * @return true if it's an int, false if not
+     */
+    public boolean isInt() {
+        return type == ENode.T_int;
+    }
+
+    /**
+     * @return true if it's a double, false if not
+     */
+    public boolean isDouble() {
+        return type == ENode.T_double;
+    }
+
+    /**
+     * @return true if it's null, false if not
+     */
+    public boolean isNull() {
+        return type == ENode.T_null;
+    }
+
+    /**
+     * Returns the adaptive type for the given class.
+     * 
+     * @param c
+     *            is the class
+     * @return the adaptive type
+     */
+    public static Class getAdapterType(Class c) {
+        if (c == ENode.class || c == EObject.class || c == ENodeList.class || c == String.class || c == boolean.class || c == int.class || c == double.class || c == null) {
+            return c;
+        } else if (EObject.class.isAssignableFrom(c)) {
+            return EObject.class;
+        } else if (c == List.class) { // List fix
+            return List.class;
+        } else if (c == Collection.class) { // Collection fix
+            return List.class;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the adaptive value for the given class.
+     * 
+     * @param c
+     *            is the class
+     * @return the adaptive value
+     */
+    public Object getAdapterValue(Class c) throws ENodeCastException {
+        if (c == EObject.class) {
+            return toEObject_().getValue();
+        } else if (c == ENodeList.class) {
+            return toList_().getValue();
+        } else if (c == String.class) {
+            return toString_().getValue();
+        } else if (c == boolean.class) {
+            return toBoolean_().getValue();
+        } else if (c == int.class) {
+            return toInt_().getValue();
+        } else if (c == double.class) {
+            return toDouble_().getValue();
+        } else if (c == null) {
+            return toNull_().getValue();
+        } else if (c == List.class) { // List fix
+            return toList_().getList().asList();
+        } else if (c == Collection.class) { // Collection fix
+            return toList_().getList().asList();
+        } else if (c == ENode.class) {
+            return this;
+        } else {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ENode.InvalidAdapterType", new Object[] { c.getClass().getName(), })); //$NON-NLS-1$
+        }
+    }
+
+    private ENode toEObject_() throws ENodeCastException {
+        if (typeClass == EObject.class) {
+            return this;
+        } else if (typeClass == ENodeList.class) {
+            if (getList().size() > 0) {
+                return getList().get(0);
+            } else {
+                return new ENode(ENode.EMPTY, this);
+            }
+        } else if (typeClass == String.class) {
+            Object result = EcoreFactory.eINSTANCE.createFromString(EcorePackage.eINSTANCE.getEString(), getString());
+            if (result instanceof EObject) {
+                return new ENode((EObject) result, this);
+            } else {
+                return new ENode(ENode.EMPTY, this);
+            }
+        } else if (typeClass == boolean.class) {
+            Object result = EcoreFactory.eINSTANCE.createFromString(EcorePackage.eINSTANCE.getEBoolean(), toString());
+            if (result instanceof EObject) {
+                return new ENode((EObject) result, this);
+            } else {
+                return new ENode(ENode.EMPTY, this);
+            }
+        } else if (typeClass == int.class) {
+            Object result = EcoreFactory.eINSTANCE.createFromString(EcorePackage.eINSTANCE.getEInt(), toString());
+            if (result instanceof EObject) {
+                return new ENode((EObject) result, this);
+            } else {
+                return new ENode(ENode.EMPTY, this);
+            }
+        } else if (typeClass == double.class) {
+            Object result = EcoreFactory.eINSTANCE.createFromString(EcorePackage.eINSTANCE.getEDouble(), toString());
+            if (result instanceof EObject) {
+                return new ENode((EObject) result, this);
+            } else {
+                return new ENode(ENode.EMPTY, this);
+            }
+        } else {
+            return new ENode(ENode.EMPTY, this);
+        }
+    }
+
+    private ENode toList_() {
+        if (typeClass == ENodeList.class) {
+            return this;
+        } else {
+            ENodeList result = new ENodeList();
+            result.add(this);
+            return new ENode(result, this);
+        }
+    }
+
+    private ENode toString_() throws ENodeCastException {
+        if (typeClass == String.class) {
+            return this;
+        } else if (typeClass == ENodeList.class) {
+            ENode result = new ENode("", this); //$NON-NLS-1$
+            ENodeIterator it = getList().iterator();
+            while (it.hasNext()) {
+                result.append(it.next());
+            }
+            return result;
+        } else {
+            return new ENode(toString(), this);
+        }
+    }
+
+    private ENode toBoolean_() throws ENodeCastException {
+        if (typeClass == EObject.class) {
+            return new ENode(true, this);
+        } else if (typeClass == ENodeList.class) {
+            return new ENode(getList().size() > 0, this);
+        } else if (typeClass == String.class) {
+            return new ENode("true".equalsIgnoreCase(getString().trim()), this); //$NON-NLS-1$
+        } else if (typeClass == boolean.class) {
+            return this;
+        } else if (typeClass == int.class) {
+            if (getInt() > 0) {
+                return new ENode(true, this);
+            } else {
+                return new ENode(false, this);
+            }
+        } else if (typeClass == double.class) {
+            if (getDouble() > 0) {
+                return new ENode(true, this);
+            } else {
+                return new ENode(false, this);
+            }
+        } else {
+            return new ENode(false, this);
+        }
+    }
+
+    private ENode toInt_() throws ENodeCastException {
+        if (typeClass == EObject.class) {
+            return new ENode(1, this);
+        } else if (typeClass == ENodeList.class) {
+            return new ENode(getList().size(), this);
+        } else if (typeClass == String.class) {
+            try {
+                return new ENode(Integer.parseInt(getString().trim()), this);
+            } catch (NumberFormatException e) {
+                throw new ENodeCastException(AcceleoGenMessages.getString("ENode.AdapterNotFound", new Object[] { "Integer", toString() + " [" + getType() + ']', })); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+            }
+        } else if (typeClass == boolean.class) {
+            if (getBoolean()) {
+                return new ENode(1, this);
+            } else {
+                return new ENode(0, this);
+            }
+        } else if (typeClass == int.class) {
+            return this;
+        } else if (typeClass == double.class) {
+            return new ENode(((Double) value).intValue(), this);
+        } else {
+            return new ENode(0, this);
+        }
+    }
+
+    private ENode toDouble_() throws ENodeCastException {
+        if (typeClass == EObject.class) {
+            return new ENode(1.0, this);
+        } else if (typeClass == ENodeList.class) {
+            return new ENode(new Double(getList().size()).doubleValue(), this);
+        } else if (typeClass == String.class) {
+            try {
+                return new ENode(Double.parseDouble(getString().trim()), this);
+            } catch (NumberFormatException e) {
+                throw new ENodeCastException(AcceleoGenMessages.getString("ENode.AdapterNotFound", new Object[] { "Double", toString() + " [" + getType() + ']', })); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+            }
+        } else if (typeClass == boolean.class) {
+            if (getBoolean()) {
+                return new ENode(1.0, this);
+            } else {
+                return new ENode(0.0, this);
+            }
+        } else if (typeClass == int.class) {
+            return new ENode(new Double(getInt()).doubleValue(), this);
+        } else if (typeClass == double.class) {
+            return this;
+        } else {
+            return new ENode(0.0, this);
+        }
+    }
+
+    private ENode toNull_() {
+        return new ENode(ENode.EMPTY, this);
+    }
+
+    /**
+     * @return the EObject value if it's an EObject
+     * @throws ENodeCastException
+     *             if it isn't an EObject
+     */
+    public EObject getEObject() throws ENodeCastException {
+        if (isEObject()) {
+            return (EObject) value;
+        } else {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ENode.ENodeCastExceptionMessage", new Object[] { type, ENode.T_EObject, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * @return the ENodeList value if it's an ENodeList
+     * @throws ENodeCastException
+     *             if it isn't an ENodeList
+     */
+    public ENodeList getList() throws ENodeCastException {
+        if (isList()) {
+            return (ENodeList) value;
+        } else {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ENode.ENodeCastExceptionMessage", new Object[] { type, ENode.T_ENodeList, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * @return the String value if it's a String
+     * @throws ENodeCastException
+     *             if it isn't a String
+     */
+    public String getString() throws ENodeCastException {
+        if (isString()) {
+            return (String) value;
+        } else {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ENode.ENodeCastExceptionMessage", new Object[] { type, ENode.T_String, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * @return the boolean value if it's a boolean
+     * @throws ENodeCastException
+     *             if it isn't a boolean
+     */
+    public boolean getBoolean() throws ENodeCastException {
+        if (isBoolean()) {
+            return ((Boolean) value).booleanValue();
+        } else {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ENode.ENodeCastExceptionMessage", new Object[] { type, ENode.T_boolean, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * @return the int value if it's an int
+     * @throws ENodeCastException
+     *             if it isn't an int
+     */
+    public int getInt() throws ENodeCastException {
+        if (isInt()) {
+            return ((Integer) value).intValue();
+        } else {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ENode.ENodeCastExceptionMessage", new Object[] { type, ENode.T_int, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * @return the double value if it's a double
+     * @throws ENodeCastException
+     *             if it isn't a double
+     */
+    public double getDouble() throws ENodeCastException {
+        if (isDouble()) {
+            return ((Double) value).doubleValue();
+        } else {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ENode.ENodeCastExceptionMessage", new Object[] { type, ENode.T_double, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * It transforms this node into String.
+     * 
+     * @return the new String value.
+     */
+    public String asString() {
+        if (isList()) {
+            try {
+                ENodeIterator it = getList().iterator();
+                init("", ENode.T_String, String.class); //$NON-NLS-1$
+                while (it.hasNext()) {
+                    ENode child = it.next();
+                    append(child);
+                }
+            } catch (ENodeCastException e) {
+                // Never catch
+            }
+        } else if (!isString()) {
+            String v = toString();
+            init(v, ENode.T_String, String.class);
+        }
+        return (String) value;
+    }
+
+    /**
+     * Appends an other node to this current node.
+     * <p>
+     * If current is null, it updates current with other node settings.
+     * <p>
+     * If current isn't null, it transforms current into String, it transforms
+     * other into String, and it appends the two node.
+     * 
+     * @param other
+     *            is the other node
+     */
+    public void append(ENode other) {
+        if (isNull() && !other.isString()) {
+            init(other.value, other.type, other.typeClass);
+            log.getAll(other.log, false);
+        } else if (other.isList()) {
+            try {
+                ENodeIterator it = other.getList().iterator();
+                while (it.hasNext()) {
+                    ENode child = it.next();
+                    append(child);
+                }
+            } catch (ENodeCastException e) {
+                // Never catch
+            }
+        } else {
+            String buffer = other.asString();
+            if (other.textModelMapping != null) {
+                other.textModelMapping.commit();
+            }
+            if (other.textTemplateElementMapping != null) {
+                other.textTemplateElementMapping.commit();
+            }
+            asString();
+            int size = size();
+            value = ((String) value) + buffer;
+            if (textModelMapping != null && other.textModelMapping != null) {
+                textModelMapping.from(other.textModelMapping);
+            }
+            if (textTemplateElementMapping != null && other.textTemplateElementMapping != null) {
+                textTemplateElementMapping.from(other.textTemplateElementMapping);
+            }
+            other.log().shiftPosition(size);
+            log.getAll(other.log, false);
+        }
+    }
+
+    /**
+     * Appends text to this node.
+     * <p>
+     * The text will have the default highlight
+     * TextModelMapping.HIGHLIGHTED_DEFAULT.
+     * 
+     * @param text
+     *            is the text to be added
+     */
+    public void append(String text) {
+        append(text, TextModelMapping.HIGHLIGHTED_DEFAULT);
+    }
+
+    /**
+     * Appends text to this node.
+     * <p>
+     * The text will have the given highlight.
+     * 
+     * @param text
+     *            is the text to be added
+     * @param highlightedType
+     *            is the highlight type.
+     */
+    public void append(String text, int highlightedType) {
+        asString();
+        value = value + text;
+        if (textModelMapping != null) {
+            textModelMapping.shift(text.length(), highlightedType);
+        }
+        if (textTemplateElementMapping != null) {
+            textTemplateElementMapping.shift(text.length(), highlightedType);
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public boolean equals(Object other) {
+        if (other != null && other instanceof ENode) {
+            try {
+                return equals((ENode) other);
+            } catch (ENodeCastException e) {
+                return false;
+            }
+        } else {
+            if (value == null && other == null) {
+                return true;
+            } else if (value == null || other == null) {
+                return false;
+            } else {
+                return value.equals(other);
+            }
+        }
+    }
+
+    /**
+     * Indicates if nodes are equals.
+     * 
+     * @param other
+     *            is the other node
+     * @return true if nodes are equals
+     * @throws ENodeCastException
+     *             if the types of the nodes are not compatible
+     */
+    public boolean equals(ENode other) throws ENodeCastException {
+        if (isNull() && other.isNull()) {
+            return true;
+        } else if (isNull() || other.isNull()) {
+            return toString().equals(other.toString());
+        } else if (type == other.type) {
+            return value.equals(other.value);
+        } else if (other.isBoolean()) {
+            return other.value.equals(getAdapterValue(other.getTypeClass()));
+        } else {
+            if (value.equals(other.getAdapterValue(getTypeClass()))) {
+                return true;
+            } else {
+                return toString().equals(other.toString());
+            }
+        }
+        // It never throws : new ENodeCastException(type + " can't be equals
+        // with " + other.type);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    /**
+     * Returns the size of the node. <li>isEObject() : return 1</li> <li>
+     * isList() : return getList().size()</li> <li>isString() : return
+     * getString().length()</li> <li>isBoolean() : return 1</li> <li>isInt() :
+     * return 1</li> <li>isDouble() : return 1</li> <li>isNull() : return 0</li>
+     * 
+     * @return value size
+     */
+    public int size() {
+        if (isEObject()) {
+            return 1;
+        } else if (isList()) {
+            return ((ENodeList) value).size();
+        } else if (isString()) {
+            return ((String) value).length();
+        } else if (isBoolean()) {
+            return 1;
+        } else if (isInt()) {
+            return 1;
+        } else if (isDouble()) {
+            return 1;
+        } else {
+            // ASSERT isNull()
+            return 0;
+        }
+    }
+
+    /* (non-Javadoc) */
+    public int compareTo(Object other) {
+        int result = 0;
+        if (other instanceof ENode) {
+            if (getValue() instanceof Comparable && ((ENode) other).getValue() instanceof Comparable) {
+                result = ((Comparable) getValue()).compareTo(((ENode) other).getValue());
+            } else {
+                result = toString().compareTo(other.toString());
+            }
+        }
+        if (result != 0) {
+            return result;
+        } else {
+            return 1;
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        if (isNull()) {
+            return ""; //$NON-NLS-1$
+        } else if (isEObject() && !(value instanceof EEnumLiteral)) {
+            EObject object = (EObject) value;
+            String buffer = object.toString();
+            int iProperties = buffer.indexOf("("); //$NON-NLS-1$
+            if (iProperties > -1) {
+                return ETools.getEClassifierShortPath(object.eClass()) + ' ' + buffer.substring(iProperties);
+            } else {
+                return value.toString();
+            }
+        } else if (isDouble()) {
+            return NumberFormat.getInstance().format(((Double) value).doubleValue());
+        } else {
+            return value.toString();
+        }
+    }
+
+    /**
+     * Indicates if it's a containment node.
+     */
+    protected boolean containment = true;
+
+    /**
+     * @return true if it's a containment node, false if not
+     */
+    public boolean isContainment() {
+        return containment;
+    }
+
+    /**
+     * @param containment
+     *            indicates if it's a containment node
+     */
+    public void setContainment(boolean containment) {
+        this.containment = containment;
+    }
+
+    /**
+     * Indicates if it's an optional node.
+     */
+    protected boolean optional = false;
+
+    /**
+     * @return true if it's an optional node, false if not
+     */
+    public boolean isOptional() {
+        return optional;
+    }
+
+    /**
+     * @param optional
+     *            indicates if it's an optional node
+     */
+    public void setOptional(boolean optional) {
+        this.optional = optional;
+    }
+
+    /**
+     * Indicates if this node is instance of the class whose name is given. <li>
+     * getType() == name => true</li> <li>isEObject() =>
+     * EFactory.eInstanceOf(getEObject(),name)</li>
+     * <p>
+     * Samples :
+     * <li>Return true if isString() and name == "String"</li>
+     * <li>An instance of the EObject java.resources.Folder</li>
+     * return true if name equals "Folder" or "resources.Folder".
+     * <li>An instance of the EObject java.resources.Folder return true if name
+     * equals "File" and Folder inherits File.</li>
+     * 
+     * @param name
+     *            is the class name
+     * @return true if this node is instance of the class whose name is given
+     */
+    public boolean eInstanceof(String name) {
+        if (getType().equals(name)) {
+            return true;
+        } else {
+            try {
+                if (EFactory.eInstanceOf(getEObject(), name)) {
+                    return true;
+                } else {
+                    return false;
+                }
+            } catch (ENodeCastException e) {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * It returns a new ENode if value is valid (EObject, ENodeList, String,
+     * Boolean, Integer, or null), else it returns null.
+     * 
+     * @param value
+     *            is the value
+     * @param parent
+     *            is the parent node
+     * @return the new ENode or null
+     */
+    public static ENode createTry(Object value, ENode parent) {
+        if (value == null) {
+            return new ENode(ENode.EMPTY, parent);
+        } else if (value instanceof ENode) {
+            ENode node = (ENode) value;
+            if (node.containerEObject == null && parent.containerEObject != null) {
+                ENode result = new ENode(ENode.EMPTY, parent);
+                result.append(node);
+                return result;
+            } else {
+                return node;
+            }
+        } else if (value instanceof EObject) {
+            if (value instanceof Enumerator) {
+                return new ENode(((Enumerator) value).getLiteral(), parent);
+            } else {
+                return new ENode((EObject) value, parent);
+            }
+        } else if (value instanceof String) {
+            return new ENode((String) value, parent);
+        } else if (value instanceof ENodeList) {
+            return new ENode((ENodeList) value, parent);
+        } else if (value instanceof Collection) {
+            ENodeList result = new ENodeList();
+            Iterator it = ((Collection) value).iterator();
+            while (it.hasNext()) {
+                ENode element = ENode.createTry(it.next(), parent);
+                if (element != null) {
+                    result.add(element);
+                }
+            }
+            return new ENode(result, parent);
+        } else if (value instanceof Object[]) {
+            ENodeList result = new ENodeList();
+            Object[] values = (Object[]) value;
+            for (Object value2 : values) {
+                ENode element = ENode.createTry(value2, parent);
+                if (element != null) {
+                    result.add(element);
+                }
+            }
+            return new ENode(result, parent);
+        } else if (value instanceof Boolean) {
+            return new ENode(((Boolean) value).booleanValue(), parent);
+        } else if (value instanceof Integer) {
+            return new ENode(((Integer) value).intValue(), parent);
+        } else if (value instanceof Short) {
+            return new ENode(((Short) value).intValue(), parent);
+        } else if (value instanceof Long) {
+            return new ENode(((Long) value).intValue(), parent);
+        } else if (value instanceof Double) {
+            return new ENode(((Double) value).doubleValue(), parent);
+        } else if (value instanceof Float) {
+            return new ENode(((Float) value).doubleValue(), parent);
+        } else if (value instanceof Character) {
+            return new ENode(String.valueOf(value), parent);
+        } else {
+            return new ENode(value.toString(), parent);
+        }
+    }
+
+    /**
+     * String method call.
+     * 
+     * @param name
+     *            is the name of the method to call
+     * @param begin
+     *            is the beginning index, or -1
+     * @param end
+     *            is the ending index, or -1
+     */
+    public void stringCall(String name, int begin, int end) {
+        if (isList()) {
+            try {
+                ENodeIterator it = getList().iterator();
+                init(new ENodeList(), ENode.T_ENodeList, ENodeList.class);
+                while (it.hasNext()) {
+                    ENode child = it.next();
+                    child.stringCall(name, begin, end);
+                    getList().add(child);
+                }
+            } catch (ENodeCastException e) {
+                // Never catch
+            }
+        } else {
+            if (!isString()) {
+                String v = toString();
+                init(v, ENode.T_String, String.class);
+            }
+            // isString
+            String text = (String) value;
+            if (text.length() > 0) {
+                if ("trim".equals(name)) { //$NON-NLS-1$
+                    Int2 range = TextSearch.getDefaultSearch().trim(text, 0, text.length());
+                    if (range.b() > 0 || range.e() < text.length()) {
+                        range(range);
+                        value = substring(text, range.b(), range.e());
+                    }
+                } else if ("substring".equals(name)) { //$NON-NLS-1$
+                    Int2 range;
+                    if (end > -1) {
+                        range = new Int2(begin, end);
+                    } else {
+                        range = new Int2(begin, text.length());
+                    }
+                    if (range.b() > 0 || range.e() < text.length()) {
+                        range(range);
+                        value = substring(text, range.b(), range.e());
+                    }
+                } else if ("toLowerCase".equals(name)) { //$NON-NLS-1$
+                    value = text.toLowerCase();
+                } else if ("toUpperCase".equals(name)) { //$NON-NLS-1$
+                    value = text.toUpperCase();
+                } else if ("toU1Case".equals(name)) { //$NON-NLS-1$
+                    value = Character.toUpperCase(text.charAt(0)) + text.substring(1);
+                } else if ("toL1Case".equals(name)) { //$NON-NLS-1$
+                    value = Character.toLowerCase(text.charAt(0)) + text.substring(1);
+                } else if ("indentSpace".equals(name) || "indentTab".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$
+                    char c = ("indentSpace".equals(name)) ? ' ' : '\t'; //$NON-NLS-1$
+                    StringBuffer buffer = new StringBuffer(text);
+                    Int2[] lines = TextSearch.getDefaultSearch().splitPositionsOf(text, new String[] { "\n" }, false); //$NON-NLS-1$
+                    indent(lines);
+                    for (int i = lines.length - 1; i >= 0; i--) {
+                        buffer.insert(lines[i].b(), c);
+                    }
+                    value = buffer.toString();
+                } else if (name != null && name.startsWith("internalIndent:")) { //$NON-NLS-1$
+                    String indent = name.substring("internalIndent:".length()); //$NON-NLS-1$
+                    StringBuffer buffer = new StringBuffer(text);
+                    Int2[] lines = TextSearch.getDefaultSearch().splitPositionsOf(text, new String[] { "\n" }, false); //$NON-NLS-1$
+                    for (int i = 0; i < indent.length(); i++) {
+                        indent(lines);
+                    }
+                    for (int i = lines.length - 1; i >= 0; i--) {
+                        buffer.insert(lines[i].b(), indent);
+                    }
+                    value = buffer.toString();
+                    stringCall("substring", indent.length(), -1); //$NON-NLS-1$
+                }
+            }
+        }
+    }
+
+    private void range(Int2 range) {
+        if (textModelMapping != null) {
+            textModelMapping.range(range);
+        }
+        if (textTemplateElementMapping != null) {
+            textTemplateElementMapping.range(range);
+        }
+        log.range(range);
+    }
+
+    private String substring(String s, int begin, int end) {
+        if (begin < 0 || end < 0 || begin >= s.length() || end <= begin) {
+            return ""; //$NON-NLS-1$
+        } else if (end >= s.length()) {
+            return s.substring(begin);
+        } else {
+            return s.substring(begin, end);
+        }
+    }
+
+    private void indent(Int2[] lines) {
+        if (textModelMapping != null) {
+            textModelMapping.indent(lines);
+        }
+        if (textTemplateElementMapping != null) {
+            textTemplateElementMapping.indent(lines);
+        }
+        log.indent(lines);
+    }
+
+    /**
+     * Creates a copy.
+     * 
+     * @return the copy
+     */
+    public ENode copy() {
+        if (value == null) {
+            return new ENode(ENode.EMPTY, this);
+        } else if (value instanceof EObject) {
+            return new ENode((EObject) value, this);
+        } else if (value instanceof String) {
+            return new ENode((String) value, this);
+        } else if (value instanceof ENodeList) {
+            return new ENode((ENodeList) value, this);
+        } else if (value instanceof Boolean) {
+            return new ENode(((Boolean) value).booleanValue(), this);
+        } else if (value instanceof Integer) {
+            return new ENode(((Integer) value).intValue(), this);
+        } else if (value instanceof Double) {
+            return new ENode(((Double) value).doubleValue(), this);
+        } else {
+            return new ENode(value.toString(), this);
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeCastException.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeCastException.java
new file mode 100644
index 0000000..d29041b
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeCastException.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import org.eclipse.sirius.query.legacy.tools.log.AcceleoException;
+
+/**
+ * ENode Cast Exception.
+ * 
+ * 
+ */
+public class ENodeCastException extends AcceleoException {
+
+    private static final long serialVersionUID = 1;
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     */
+    public ENodeCastException(String message) {
+        super(message);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getMessage() {
+        return super.getMessage();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeException.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeException.java
new file mode 100644
index 0000000..8f61722
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeException.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.log.AcceleoException;
+import org.eclipse.sirius.query.legacy.tools.log.Trace;
+import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoModuleProvider;
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * ENode Exception.
+ * 
+ */
+public class ENodeException extends AcceleoException {
+
+    private static final long serialVersionUID = 1;
+
+    /**
+     * The identifier of the runtime error marker.
+     */
+    public static final String RUNTIME_ERROR_MARKER_ID = "org.eclipse.sirius.query.legacy.gen.ui.problem"; //$NON-NLS-1$
+
+    /**
+     * The model attribute for the runtime error marker.
+     */
+    public static final String RUNTIME_ERROR_MARKER_MODEL = "runmodel"; //$NON-NLS-1$
+
+    /**
+     * The fragment attribute for the runtime error marker.
+     */
+    public static final String RUNTIME_ERROR_MARKER_FRAGMENT = "runfragment"; //$NON-NLS-1$
+
+    /**
+     * Position of the evaluation error in the script.
+     */
+    protected Int2 pos;
+
+    /**
+     * Script that launch the evaluation error.
+     */
+    protected IScript script;
+
+    /**
+     * The current object of the model (EObject or ENode).
+     */
+    protected Object object;
+
+    /**
+     * Optional runtime exception.
+     */
+    protected Throwable exception;
+
+    /**
+     * Indicates if the runtime markers are activated.
+     */
+    private static boolean runtimeMarker = true;
+
+    /**
+     * The trigger to disable markers.
+     */
+    private static Object disabledTrigger = null;
+
+    /**
+     * The runtime markers are disabled.
+     * 
+     * @param source
+     *            is the trigger object
+     */
+    public static void disableRuntimeMarkersFor(Object source) {
+        if (ENodeException.runtimeMarker && ENodeException.disabledTrigger == null) {
+            ENodeException.runtimeMarker = false;
+            ENodeException.disabledTrigger = source;
+        }
+    }
+
+    /**
+     * The runtime markers are enabled.
+     * 
+     * @param source
+     *            is the trigger object
+     */
+    public static void enableRuntimeMarkersFor(Object source) {
+        if (!ENodeException.runtimeMarker && source == ENodeException.disabledTrigger) {
+            ENodeException.runtimeMarker = true;
+            ENodeException.disabledTrigger = null;
+        }
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     * @param pos
+     *            is the position of the evaluation error in the script
+     * @param script
+     *            is the script
+     * @param object
+     *            is the current object of the model (EObject or ENode)
+     * @param report
+     *            indicates if this exception has to be reported in the error
+     *            log
+     */
+    public ENodeException(String message, Int2 pos, IScript script, Object object, boolean report) {
+        this(message, pos, script, object, report, null);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     * @param pos
+     *            is the position of the evaluation error in the script
+     * @param script
+     *            is the script
+     * @param object
+     *            is the current object of the model (EObject or ENode)
+     * @param report
+     *            indicates if this exception has to be reported in the error
+     *            log
+     * @param exception
+     *            is an optional runtime exception
+     */
+    public ENodeException(String message, Int2 pos, IScript script, Object object, boolean report, Throwable exception) {
+        super(message);
+        this.pos = pos;
+        this.script = script;
+        this.object = object;
+        this.exception = exception;
+        if (report && ENodeException.runtimeMarker) {
+            getErrorMessage(true);
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getMessage() {
+        return getErrorMessage(false);
+    }
+
+    private String getErrorMessage(boolean report) {
+        // FIXME NLS should unit test this method to ensure messages are still
+        // accurate
+        String errorMessage = super.getMessage();
+        String extendedErrorMessage = new String();
+        if (script.getFile() != null) {
+            String path = script.getFile().getAbsolutePath();
+            IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(path));
+            if (workspaceFile == null || !workspaceFile.isAccessible()) {
+                String relativePath = AcceleoModuleProvider.getDefault().getRelativePath(script.getFile());
+                if (relativePath != null) {
+                    String pluginId = AcceleoModuleProvider.getDefault().getPluginId(script.getFile());
+                    if (pluginId != null) {
+                        path = new Path('/' + pluginId).append(relativePath).toString();
+                    }
+                }
+            } else {
+                path = workspaceFile.getFullPath().toString();
+            }
+
+            Int2[] newLines = TextSearch.getDefaultSearch().allIndexIn(Resources.getFileContent(script.getFile()).toString(), "\n", 0, pos.b()); //$NON-NLS-1$
+            int line = newLines.length + 1;
+            int column = pos.b();
+            if (newLines.length > 0) {
+                column = column - newLines[newLines.length - 1].e();
+            }
+            extendedErrorMessage = AcceleoGenMessages
+                    .getString("ENodeException.ExtendedErrorMessage.KnownFile", new Object[] { errorMessage, path, Integer.toString(line), Integer.toString(column), }); //$NON-NLS-1$		
+        } else {
+            if (pos.b() > 0) {
+                extendedErrorMessage = AcceleoGenMessages.getString(
+                        "ENodeException.ExtendedErrorMessage.UnknownFile", new Object[] { errorMessage, Integer.toString(pos.b()), Integer.toString(pos.e()), }); //$NON-NLS-1$
+            }
+        }
+        String modelURI = ""; //$NON-NLS-1$
+        String fragmentURI = ""; //$NON-NLS-1$
+        if (object != null) {
+            Object object = this.object;
+            if (object instanceof ENode) {
+                if (((ENode) object).isEObject()) {
+                    try {
+                        object = ((ENode) object).getEObject();
+                    } catch (ENodeCastException e) {
+                        // Never catch
+                    }
+                } else if (((ENode) object).isList()) {
+                    extendedErrorMessage += AcceleoGenMessages.getString("ENodeException.ExtendedErrorMessage.NodeFragment", new Object[] { ((ENode) object).getType(), }); //$NON-NLS-1$ 
+                    object = ((ENode) object).getContainerEObject();
+                } else {
+                    extendedErrorMessage += AcceleoGenMessages.getString("ENodeException.ExtendedErrorMessage.NodeFragment", new Object[] { ((ENode) object).getType(), }); //$NON-NLS-1$
+                    extendedErrorMessage += " : " + ((ENode) object).toString(); //$NON-NLS-1$
+                    object = ((ENode) object).getContainerEObject();
+                }
+            }
+            if (object instanceof EObject) {
+                try {
+                    fragmentURI = ETools.getURI((EObject) object);
+                } catch (UnsupportedOperationException e) {
+                    // we know some ResourceImpl will throw this Exception if
+                    // the getURIFragment is not
+                    // supported, (like CDOResource for instance). We don't want
+                    // to process to fail just for
+                    // an error during the message creation.
+                }
+                if (((EObject) object).eResource() != null) {
+                    URI uri = ((EObject) object).eResource().getURI();
+                    modelURI = (uri != null) ? uri.path() : ""; //$NON-NLS-1$
+                    extendedErrorMessage += AcceleoGenMessages.getString("ENodeException.ExtendedErrorMessage.ObjectFragmentKnownResource", new Object[] { fragmentURI, modelURI, }); //$NON-NLS-1$
+                } else {
+                    extendedErrorMessage += AcceleoGenMessages.getString(
+                            "ENodeException.ExtendedErrorMessage.ObjectFragmentUnknownResource", new Object[] { fragmentURI, ((EObject) object).eClass().getName(), object.toString(), }); //$NON-NLS-1$
+                }
+            }
+        }
+        if (exception != null) {
+            extendedErrorMessage += '\n' + Trace.getStackTrace(exception);
+        }
+
+        return extendedErrorMessage;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeIterator.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeIterator.java
new file mode 100644
index 0000000..5a759bf
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeIterator.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator over an ENodeList
+ * 
+ * 
+ */
+public class ENodeIterator {
+
+    /**
+     * The iterator.
+     */
+    protected Iterator iterator;
+
+    /**
+     * Creates an iterator over the elements in the given list.
+     * 
+     * @param list
+     *            is the list
+     */
+    protected ENodeIterator(ENodeList list) {
+        iterator = list.list.iterator();
+    }
+
+    /**
+     * Returns true if the iteration has more elements.
+     * 
+     * @return true if the iterator has more elements
+     */
+    public boolean hasNext() {
+        return iterator.hasNext();
+    }
+
+    /**
+     * Returns the next ENode in the iteration.
+     * 
+     * @return the next ENode in the iteration
+     * @throws NoSuchElementException
+     *             - iteration has no more elements
+     */
+    public ENode next() {
+        return (ENode) iterator.next();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeList.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeList.java
new file mode 100644
index 0000000..7a00493
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/ENodeList.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * List of ENode.
+ * 
+ * 
+ */
+public class ENodeList {
+
+    /**
+     * List of elements.
+     */
+    protected List list = new ArrayList();
+
+    /**
+     * Indicates that each element appears only one time in the list.
+     */
+    protected boolean unique;
+
+    /**
+     * Constructor.
+     */
+    public ENodeList() {
+        this(false);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param unique
+     *            indicates that each element appears only one time in the list
+     */
+    public ENodeList(boolean unique) {
+        super();
+        this.unique = unique;
+    }
+
+    /**
+     * Appends the specified ENode to the end of this list.
+     * 
+     * @param node
+     *            is the element to be appended to this list
+     */
+    public void add(ENode node) {
+        if (node != null) {
+            if (node.isList()) {
+                try {
+                    addAll(node.getList());
+                } catch (ENodeCastException e) {
+                    // Never catch
+                }
+            } else if (!node.isNull()) {
+                if (unique) {
+                    if (!list.contains(node)) {
+                        list.add(node);
+                    }
+                } else {
+                    list.add(node);
+                }
+            }
+        }
+    }
+
+    /**
+     * Inserts the specified ENode at the given index of this list.
+     * 
+     * @param index
+     *            is the index
+     * @param node
+     *            is the element to insert
+     */
+    public void add(int index, ENode node) {
+        if (node != null) {
+            if (node.isList()) {
+                try {
+                    addAll(index, node.getList());
+                } catch (ENodeCastException e) {
+                    // Never catch
+                }
+            } else if (!node.isNull()) {
+                if (index < 0 || index >= list.size()) {
+                    if (unique) {
+                        if (!list.contains(node)) {
+                            list.add(node);
+                        }
+                    } else {
+                        list.add(node);
+                    }
+                } else {
+                    if (unique) {
+                        if (!list.contains(node)) {
+                            list.add(index, node);
+                        }
+                    } else {
+                        list.add(index, node);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the ENode at the given index, or null if the index is out of
+     * bounds.
+     * 
+     * @param index
+     *            is the index
+     * @return the ENode at the given index, or null if the index is out of
+     *         bounds
+     */
+    public ENode get(int index) {
+        if (index >= 0 && index < list.size()) {
+            return (ENode) list.get(index);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Removes the first occurrence in this list of the specified ENode.
+     * 
+     * @param node
+     *            is the element to be removed from this list, if present
+     */
+    public void remove(ENode node) {
+        list.remove(node);
+    }
+
+    /**
+     * Appends all of the elements in the specified ENodeList to the end of this
+     * list.
+     * 
+     * @param other
+     *            is ENodeList whose elements are to be added to this list
+     */
+    public void addAll(ENodeList other) {
+        ENodeIterator it = other.iterator();
+        while (it.hasNext()) {
+            add(it.next());
+        }
+    }
+
+    private void addAll(int index, ENodeList other) {
+        ENodeIterator it = other.iterator();
+        while (it.hasNext()) {
+            add(index, it.next());
+        }
+    }
+
+    /**
+     * Returns an iterator over the elements in this list in proper sequence.
+     * 
+     * @return an iterator over the elements in this list in proper sequence
+     */
+    public ENodeIterator iterator() {
+        return new ENodeIterator(this);
+    }
+
+    /**
+     * Gets an array representation of the list.
+     * 
+     * @return an array representation of the list
+     */
+    public Object[] toArray() {
+        return list.toArray();
+    }
+
+    /**
+     * Returns true if this list contains the specified element.
+     * <p>
+     * More formally, returns true if and only if this list contains at least
+     * <p>
+     * one element e such that (o==null ? e==null : o.equals(e)).
+     * 
+     * @param node
+     *            is element whose presence in this list is to be tested
+     * @return true if this list contains the specified element
+     */
+    public boolean contains(ENode node) {
+        return list.contains(node);
+    }
+
+    /**
+     * Returns the number of elements in this list.
+     * 
+     * @return the number of elements in this list
+     */
+    public int size() {
+        return list.size();
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        StringBuffer buffer = new StringBuffer(""); //$NON-NLS-1$
+        ENodeIterator it = iterator();
+        while (it.hasNext()) {
+            buffer.append(it.next().toString());
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Sorts the list using "toString" result.
+     */
+    public void sort() {
+        Set set = new TreeSet(new Comparator() {
+            public int compare(Object arg0, Object arg1) {
+                return ((ENode) arg0).compareTo((arg1));
+            }
+        });
+        set.addAll(list);
+        list = new ArrayList(set);
+    }
+
+    /**
+     * Gets a list representation of the ENodeList.
+     * 
+     * @return a list representation of the ENodeList
+     */
+    public List asList() {
+        List result = new ArrayList();
+        ENodeIterator it = iterator();
+        while (it.hasNext()) {
+            result.add(it.next().getValue());
+        }
+        return result;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public boolean equals(Object arg0) {
+        if (arg0 instanceof ENodeList) {
+            return list.equals(((ENodeList) arg0).list);
+        }
+        return false;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/LaunchManager.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/LaunchManager.java
new file mode 100644
index 0000000..917b98e
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/LaunchManager.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * The launch manager : the mode in which to launch - RUN_MODE, DEBUG_MODE, or
+ * PREVIEW_MODE.
+ * 
+ * 
+ */
+public class LaunchManager {
+
+    /**
+     * The mode in which to launch : RUN_MODE.
+     */
+    public static final int RUN_MODE = 1;
+
+    /**
+     * The mode in which to launch : DEBUG_MODE.
+     */
+    public static final int DEBUG_MODE = 2;
+
+    /**
+     * The mode in which to launch : PREVIEW_MODE.
+     */
+    public static final int PREVIEW_MODE = 3;
+
+    /**
+     * The mode in which to launch : PHANTOM_MODE.
+     */
+    public static final int PHANTOM_MODE = 4;
+
+    /**
+     * The mode in which to launch.
+     */
+    private final int mode;
+
+    /**
+     * Activates text/model synchronization.
+     */
+    private boolean synchronize;
+
+    /**
+     * The progress monitor;
+     */
+    private IProgressMonitor monitor;
+
+    private boolean profiling;
+
+    private boolean logEObject;
+
+    /**
+     * Constructor.
+     * 
+     * @param mode
+     *            is mode in which to launch
+     * @param synchronize
+     *            activates text/model synchronization
+     */
+    private LaunchManager(int mode, boolean synchronize) {
+        this.mode = mode;
+        this.synchronize = synchronize;
+    }
+
+    /**
+     * Creates a new manager.
+     * 
+     * @param mode
+     *            is a string - "run", "debug", "preview", "phantom", "profile"
+     * @param synchronize
+     *            indicates if the text/model synchronization is activated
+     * @return the manager or null
+     */
+    public static LaunchManager create(String mode, boolean synchronize) {
+        if (mode == null) {
+            return null;
+        } else if (mode.equals("run")) { //$NON-NLS-1$
+            return new LaunchManager(LaunchManager.RUN_MODE, synchronize);
+        } else if (mode.equals("debug")) { //$NON-NLS-1$
+            return new LaunchManager(LaunchManager.DEBUG_MODE, synchronize);
+        } else if (mode.equals("preview")) { //$NON-NLS-1$
+            return new LaunchManager(LaunchManager.PREVIEW_MODE, synchronize);
+        } else if (mode.equals("phantom")) { //$NON-NLS-1$
+            return new LaunchManager(LaunchManager.PHANTOM_MODE, synchronize);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @return the mode in which to launch
+     */
+    public int getMode() {
+        return mode;
+    }
+
+    /**
+     * @return true if the text/model synchronization is activated
+     */
+    public boolean isSynchronize() {
+        return synchronize;
+    }
+
+    /**
+     * @param synchronize
+     *            indicates if the text/model synchronization is activated
+     */
+    public void setSynchronize(boolean synchronize) {
+        this.synchronize = synchronize;
+    }
+
+    /**
+     * @return the monitor
+     */
+    public IProgressMonitor getMonitor() {
+        return monitor;
+    }
+
+    /**
+     * @param monitor
+     *            is the monitor to set
+     */
+    public void setMonitor(IProgressMonitor monitor) {
+        this.monitor = monitor;
+    }
+
+    /**
+     * @return true if the profiling is activated
+     */
+    public boolean isProfiling() {
+        return profiling;
+    }
+
+    /**
+     * @return true if the profiling of EObjects is activated
+     */
+    public boolean isLoggingEObject() {
+        return logEObject;
+    }
+
+    /**
+     * Turn EObjects profiling on.
+     */
+    public void logEObjects() {
+        logEObject = true;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/StringComparator.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/StringComparator.java
new file mode 100644
index 0000000..4fe6a2a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/StringComparator.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * A string comparator.
+ * 
+ * 
+ */
+public class StringComparator implements Comparator, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /* (non-Javadoc) */
+    public int compare(Object arg0, Object arg1) {
+        return ((String) arg0).compareTo((String) arg1);
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/TextModelMapping.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/TextModelMapping.java
new file mode 100644
index 0000000..774ad1a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/TextModelMapping.java
@@ -0,0 +1,745 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * Mapping between the model and the text value.
+ * 
+ * 
+ */
+public class TextModelMapping {
+
+    /**
+     * The element that compares positions (Int2).
+     */
+    private static class InversePosComparator implements Comparator, Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        public int compare(Object arg0, Object arg1) {
+            Int2 pos0 = ((Int2) arg0);
+            Int2 pos1 = ((Int2) arg1);
+            if (pos0.b() < pos1.b()) {
+                return 1;
+            } else if (pos0.b() > pos1.b()) {
+                return -1;
+            } else {
+                if (pos0.e() < pos1.e()) {
+                    return -1;
+                } else if (pos0.e() > pos1.e()) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        }
+    }
+
+    /**
+     * The element that compares positions (Int2).
+     */
+    private static class PosComparator implements Comparator {
+        /**
+         * {@inheritDoc}
+         */
+        public int compare(Object arg0, Object arg1) {
+            Int2 pos0 = ((Int2) arg0);
+            Int2 pos1 = ((Int2) arg1);
+            int res;
+            if (pos0.b() < pos1.b()) {
+                res = -1;
+            } else if (pos0.b() > pos1.b()) {
+                res = 1;
+            } else {
+                if (pos0.e() < pos1.e()) {
+                    res = 1;
+                } else if (pos0.e() > pos1.e()) {
+                    res = -1;
+                } else {
+                    res = 0;
+                }
+            }
+            return res;
+        }
+    }
+
+    /**
+     * An object that maps text position to EObject.
+     */
+    protected Map pos2EObject = new TreeMap(new InversePosComparator());
+
+    /**
+     * An object that maps EObject to text position.
+     */
+    protected Map eObject2Positions = new HashMap();
+
+    /**
+     * An object that maps EObject to comment text position.
+     */
+    protected Map eObject2CommentPositions = new HashMap();
+
+    /**
+     * An object that maps text position to an EObject declaration. It is used
+     * for an open link action.
+     */
+    protected Map pos2LinkEObject = new TreeMap(new InversePosComparator());
+
+    /**
+     * Highlight positions.
+     * <p>
+     * <li>highlightedPos[HIGHLIGHTED_STATIC_TEXT] is a list of positions for
+     * the text which is not in the models.</li>
+     * <li>highlightedPos[HIGHLIGHTED_COMMENT] is a list of positions for
+     * comments.</li>
+     */
+    protected List[] highlightedPos = new List[2];
+
+    // Default highlight.
+    public static final int HIGHLIGHTED_DEFAULT = -1;
+
+    // Highlight for the text which is not in the models.
+    public static final int HIGHLIGHTED_STATIC_TEXT = 0;
+
+    // Highlight for comments.
+    public static final int HIGHLIGHTED_COMMENT = 1;
+
+    /**
+     * Default object for text mapping.
+     */
+    protected EObject object;
+
+    /**
+     * Current size of the text used for the mapping.
+     */
+    protected int shift;
+
+    /**
+     * Indicates if the changes were validated.
+     * <p>
+     * It is impossible to change mappings when commit is true.
+     */
+    protected boolean commit = false;
+
+    /**
+     * Constructor.
+     * 
+     * @param object
+     *            is the default object for text mapping
+     * @param freeze
+     *            is used to freeze the mappings, this helps to improve the
+     *            performance
+     */
+    public TextModelMapping(EObject object, boolean freeze) {
+        this.object = object;
+        for (int i = 0; i < highlightedPos.length; i++) {
+            if (highlightedPos[i] == null) {
+                highlightedPos[i] = new ArrayList();
+            }
+        }
+        if (freeze) {
+            commit = true;
+        } else {
+            reset();
+        }
+    }
+
+    /**
+     * Reset all informations.
+     */
+    protected void reset() {
+        if (!commit) {
+            this.shift = 0;
+            pos2EObject.clear();
+            index2EObjects.clear();
+            eObject2Positions.clear();
+            eObject2CommentPositions.clear();
+            pos2LinkEObject.clear();
+            index2LinkEObject.clear();
+            for (int i = 0; i < highlightedPos.length; i++) {
+                if (highlightedPos[i] != null) {
+                    highlightedPos[i].clear();
+                } else {
+                    highlightedPos[i] = new ArrayList();
+                }
+            }
+        }
+    }
+
+    /**
+     * Appends other mappings to current mappings.
+     * 
+     * @param other
+     *            is the other mappings between the model and the text value
+     */
+    public void from(TextModelMapping other) {
+        if (!commit && other != null) {
+            // mapping pos2EObject, eObject2Pos
+            Iterator it = other.pos2EObject.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = shift + ((Int2) entry.getKey()).b();
+                int e = shift + ((Int2) entry.getKey()).e();
+                EObject object = (EObject) entry.getValue();
+                addMapping(object, b, e);
+            }
+            // mapping eObject2CommentPositions
+            it = other.eObject2CommentPositions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    int b = shift + pos.b();
+                    int e = shift + pos.e();
+                    EObject object = (EObject) entry.getKey();
+                    addCommentMapping(object, b, e);
+                }
+            }
+            // mapping pos2LinkEObject
+            it = other.pos2LinkEObject.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = shift + ((Int2) entry.getKey()).b();
+                int e = shift + ((Int2) entry.getKey()).e();
+                EObject object = (EObject) entry.getValue();
+                pos2LinkEObject.put(new Int2(b, e), object);
+            }
+            // highlightedPos
+            for (int i = 0; i < other.highlightedPos.length; i++) {
+                it = other.highlightedPos[i].iterator();
+                while (it.hasNext()) {
+                    Int2 pos = (Int2) it.next();
+                    highlightedPos[i].add(new Int2(shift + pos.b(), shift + pos.e()));
+                }
+            }
+            // shift
+            shift += other.shift;
+        }
+    }
+
+    /**
+     * Returns all used objects.
+     * 
+     * @return all used objects
+     */
+    public Set getEObjects() {
+        return eObject2Positions.keySet();
+    }
+
+    /**
+     * Shifts text positions used for the mapping and puts the default
+     * highlight.
+     * 
+     * @param size
+     *            is the size of the shift
+     */
+    public void shift(int size) {
+        shift(size, TextModelMapping.HIGHLIGHTED_DEFAULT);
+    }
+
+    /**
+     * Shifts text positions used for the mapping and puts the given highlight.
+     * 
+     * @param size
+     *            is the size of the shift
+     * @param highlightedType
+     *            is the text highlight
+     */
+    public void shift(int size, int highlightedType) {
+        if (!commit) {
+            if (linkEObject != null) {
+                Int2 pos = new Int2(shift, shift + size);
+                pos2LinkEObject.put(pos, linkEObject);
+            }
+            if (highlightedType == TextModelMapping.HIGHLIGHTED_STATIC_TEXT) {
+                Int2 pos = new Int2(shift, shift + size);
+                highlightedPos[TextModelMapping.HIGHLIGHTED_STATIC_TEXT].add(pos);
+            } else if (highlightedType == TextModelMapping.HIGHLIGHTED_COMMENT) {
+                Int2 pos = new Int2(shift, shift + size);
+                highlightedPos[TextModelMapping.HIGHLIGHTED_COMMENT].add(pos);
+                addCommentMapping(object, pos.b(), pos.e());
+            }
+            shift += size;
+        }
+    }
+
+    /**
+     * Adds a mapping between the model object and the text begins at the
+     * specified begin and extends to the character at index end - 1.
+     * 
+     * @param object
+     *            is the model object
+     * @param begin
+     *            is the beginning index, inclusive
+     * @param end
+     *            is the ending index, exclusive
+     */
+    protected void addMapping(EObject object, int begin, int end) {
+        if (begin > -1 && end > -1) {
+            // Mapping pos2EObject
+            Int2 newPos = new Int2(begin, end);
+            if (!pos2EObject.containsKey(newPos)) {
+                pos2EObject.put(newPos, object);
+            }
+            // Mapping eObject2Pos
+            List objectPositions = (List) eObject2Positions.get(object);
+            if (objectPositions == null) {
+                objectPositions = new ArrayList();
+                eObject2Positions.put(object, objectPositions);
+            }
+            add(objectPositions, begin, end);
+        }
+    }
+
+    /**
+     * Adds a comment mapping between the model object and the text begins at
+     * the specified begin and extends to the character at index end - 1.
+     * 
+     * @param object
+     *            is the model object
+     * @param begin
+     *            is the beginning index, inclusive
+     * @param end
+     *            is the ending index, exclusive
+     */
+    protected void addCommentMapping(EObject object, int begin, int end) {
+        if (begin > -1 && end > -1) {
+            List commentPositions = (List) eObject2CommentPositions.get(object);
+            if (commentPositions == null) {
+                commentPositions = new ArrayList();
+                eObject2CommentPositions.put(object, commentPositions);
+            }
+            add(commentPositions, begin, end);
+        }
+    }
+
+    /**
+     * Amalgamates the new position and the other positions.
+     * 
+     * @param positions
+     *            is the list of positions
+     * @param begin
+     *            is the beginning index of the new position, inclusive
+     * @param end
+     *            is the ending index of the new position, exclusive
+     */
+    private void add(List positions, int begin, int end) {
+        boolean insert = false;
+        Iterator it = positions.iterator();
+        while (!insert && it.hasNext()) {
+            Int2 pos = (Int2) it.next();
+            if (begin <= pos.e() && begin >= pos.b()) {
+                if (end > pos.e()) {
+                    positions.remove(pos);
+                    add(positions, pos.b(), end);
+                }
+                insert = true;
+            } else if (end >= pos.b() && end <= pos.e()) {
+                if (begin < pos.b()) {
+                    positions.remove(pos);
+                    add(positions, begin, pos.e());
+                }
+                insert = true;
+            } else if (begin < pos.b() && end > pos.e()) {
+                positions.remove(pos);
+                add(positions, begin, end);
+                insert = true;
+            }
+        }
+        if (!insert) {
+            positions.add(new Int2(begin, end));
+        }
+    }
+
+    /**
+     * Marks the begin of an open link action.
+     * 
+     * @param linkEObject
+     *            is the linked object
+     */
+    public void linkBegin(EObject linkEObject) {
+        this.linkEObject = linkEObject;
+    }
+
+    /**
+     * Marks the end of the current open link action.
+     */
+    public void linkEnd() {
+        this.linkEObject = null;
+    }
+
+    /**
+     * Open link result for the next added text
+     */
+    protected EObject linkEObject = null;
+
+    /**
+     * Validate the changes.
+     * <p>
+     * It is impossible to change mappings now.
+     */
+    protected void commit() {
+        if (!commit) {
+            commit = true;
+            addMapping(object, 0, shift);
+        }
+    }
+
+    /**
+     * Returns the object at the given index.
+     * 
+     * @param index
+     *            is the position in the text
+     * @return the object at the index.
+     */
+    public EObject index2EObject(int index) {
+        List eObjects = index2EObjects(index);
+        EObject res = null;
+        if (eObjects != null && eObjects.size() > 0) {
+            res = (EObject) eObjects.get(0);
+        }
+        return res;
+    }
+
+    /**
+     * Returns objects at the given index.
+     * 
+     * @param index
+     *            is the position in the text
+     * @return objects at the index.
+     */
+    public List index2EObjects(int index) {
+        List eObjects = (List) index2EObjects.get(new Integer(index));
+        if (eObjects == null) {
+            eObjects = new ArrayList();
+            if (!commit) {
+                commit();
+            }
+            Iterator it = pos2EObject.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = ((Int2) entry.getKey()).b();
+                if (index >= b) {
+                    int e = ((Int2) entry.getKey()).e();
+                    if (index < e) {
+                        eObjects.add(entry.getValue());
+                    }
+                }
+            }
+            index2EObjects.put(new Integer(index), eObjects);
+        }
+        return eObjects;
+    }
+
+    private Map index2EObjects = new HashMap();
+
+    /**
+     * Gets a serializable object that maps the ranges of the text and the URIs
+     * of the model's objects.
+     * 
+     * @return a serializable map
+     * @deprecated
+     */
+    @Deprecated
+    public Map position2uriSerializableMap() {
+        Map result = new TreeMap(new InversePosComparator());
+        if (!commit) {
+            commit();
+        }
+        Iterator it = pos2EObject.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            Int2 pos = (Int2) entry.getKey();
+            EObject object = (EObject) entry.getValue();
+            String uriFragment = ETools.getURI(object);
+            result.put(pos, uriFragment);
+        }
+        return result;
+    }
+
+    /**
+     * Returns the positions of the given object.
+     * 
+     * @param object
+     *            is the model object
+     * @return the positions of the object
+     */
+    public Int2[] eObject2Positions(EObject object) {
+        if (object == null) {
+            return new Int2[] {};
+        }
+        if (!commit) {
+            commit();
+        }
+        List positions = (List) eObject2Positions.get(object);
+        if (positions != null) {
+            return (Int2[]) positions.toArray(new Int2[positions.size()]);
+        } else {
+            return new Int2[] {};
+        }
+    }
+
+    /**
+     * Gets a serializable object that maps the URIs of the model's objects and
+     * the ranges of the text.
+     * 
+     * @return a serializable map
+     * @deprecated
+     */
+    @Deprecated
+    public Map uri2positionsSerializableMap() {
+        Map result = new TreeMap(new StringComparator());
+        if (!commit) {
+            commit();
+        }
+        Iterator entries = eObject2Positions.entrySet().iterator();
+        while (entries.hasNext()) {
+            Map.Entry entry = (Map.Entry) entries.next();
+            EObject object = (EObject) entry.getKey();
+            String uriFragment = ETools.getURI(object);
+            Set positions = new TreeSet(new PosComparator());
+            positions.addAll((List) entry.getValue());
+            result.put(uriFragment, positions.toArray(new Int2[positions.size()]));
+        }
+        return result;
+    }
+
+    /**
+     * Returns the first comment position of the given object.
+     * 
+     * @param object
+     *            is the model object
+     * @param limits
+     *            delimits the part of the text where the comment can be
+     *            searched
+     * @return the first comment position of the object
+     */
+    public Int2 eObject2CommentPositionIn(EObject object, Int2 limits) {
+        if (object == null) {
+            return Int2.NOT_FOUND;
+        }
+        if (!commit) {
+            commit();
+        }
+        List positions = (List) eObject2CommentPositions.get(object);
+        if (positions != null) {
+            Iterator it = positions.iterator();
+            while (it.hasNext()) {
+                Int2 pos = (Int2) it.next();
+                if (pos.b() >= limits.b() && pos.e() <= limits.e()) {
+                    return pos;
+                }
+            }
+        }
+        return Int2.NOT_FOUND;
+    }
+
+    /**
+     * Returns the linked object at the given index. It is used to make an open
+     * link action.
+     * 
+     * @param index
+     *            is the position in the text
+     * @return the linked object at the index
+     */
+    public EObject index2LinkEObject(int index) {
+        EObject object = (EObject) index2LinkEObject.get(new Integer(index));
+        if (object == null) {
+            if (!commit) {
+                commit();
+            }
+            Iterator it = pos2LinkEObject.entrySet().iterator();
+            while (object == null && it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = ((Int2) entry.getKey()).b();
+                if (index >= b) {
+                    int e = ((Int2) entry.getKey()).e();
+                    if (index < e) {
+                        object = (EObject) entry.getValue();
+                    }
+                }
+            }
+            index2LinkEObject.put(new Integer(index), object);
+        }
+        return object;
+    }
+
+    private Map index2LinkEObject = new HashMap();
+
+    /**
+     * Returns all positions for the given highlight.
+     * 
+     * @param highlightedType
+     *            is the text highlight
+     * @return all positions for the given highlight
+     */
+    public Int2[] getHighlightedPos(int highlightedType) {
+        if (highlightedType == TextModelMapping.HIGHLIGHTED_STATIC_TEXT) {
+            return (Int2[]) highlightedPos[TextModelMapping.HIGHLIGHTED_STATIC_TEXT].toArray(new Int2[] {});
+        } else if (highlightedType == TextModelMapping.HIGHLIGHTED_COMMENT) {
+            return (Int2[]) highlightedPos[TextModelMapping.HIGHLIGHTED_COMMENT].toArray(new Int2[] {});
+        } else {
+            return new Int2[] {};
+        }
+    }
+
+    /**
+     * Moves the positions into the given range
+     * 
+     * @param range
+     *            are the new bounds
+     */
+    public void range(Int2 range) {
+        if (!commit) {
+            shift = range.e() - range.b();
+            // mapping pos2EObject
+            Iterator it = pos2EObject.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                Int2 pos = (Int2) entry.getKey();
+                Int2 copy = new Int2(pos.b(), pos.e());
+                copy.range(range);
+                if (copy.b() == -1 || (!copy.equals(pos) && pos2EObject.containsKey(copy))) {
+                    it.remove();
+                } else {
+                    pos.range(range);
+                }
+            }
+            // mapping eObject2Positions
+            it = eObject2Positions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.range(range);
+                    if (pos.b() == -1) {
+                        positions.remove();
+                    }
+                }
+            }
+            // mapping eObject2CommentPositions
+            it = eObject2CommentPositions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.range(range);
+                    if (pos.b() == -1) {
+                        positions.remove();
+                    }
+                }
+            }
+            // mapping pos2LinkEObject
+            it = pos2LinkEObject.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                Int2 pos = (Int2) entry.getKey();
+                Int2 copy = new Int2(pos.b(), pos.e());
+                copy.range(range);
+                if (copy.b() == -1 || (!copy.equals(pos) && pos2LinkEObject.containsKey(copy))) {
+                    it.remove();
+                } else {
+                    pos.range(range);
+                }
+            }
+            // highlightedPos
+            for (List highlightedPo : highlightedPos) {
+                it = highlightedPo.iterator();
+                while (it.hasNext()) {
+                    Int2 pos = (Int2) it.next();
+                    pos.range(range);
+                    if (pos.b() == -1) {
+                        it.remove();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Applies the indent strategy to the positions (each line adds one
+     * character).
+     * 
+     * @param lines
+     *            are the positions of the lines
+     */
+    public void indent(Int2[] lines) {
+        if (!commit) {
+            shift += lines.length;
+            // mapping pos2EObject
+            Iterator it = pos2EObject.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                ((Int2) entry.getKey()).indent(lines);
+            }
+            // mapping eObject2Positions
+            it = eObject2Positions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.indent(lines);
+                }
+            }
+            // mapping eObject2CommentPositions
+            it = eObject2CommentPositions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.indent(lines);
+                }
+            }
+            // mapping pos2LinkEObject
+            it = pos2LinkEObject.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                ((Int2) entry.getKey()).indent(lines);
+            }
+            // highlightedPos
+            for (List highlightedPo : highlightedPos) {
+                it = highlightedPo.iterator();
+                while (it.hasNext()) {
+                    Int2 pos = (Int2) it.next();
+                    pos.indent(lines);
+                }
+            }
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/TextTemplateElementMapping.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/TextTemplateElementMapping.java
new file mode 100644
index 0000000..60a4df9
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/TextTemplateElementMapping.java
@@ -0,0 +1,725 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.eclipse.sirius.query.legacy.gen.template.TemplateElement;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * Mapping between the template and the text value.
+ * 
+ * 
+ */
+public class TextTemplateElementMapping {
+
+    /**
+     * The element that compares positions (Int2).
+     */
+    private static class InversePosComparator implements Comparator, Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        public int compare(Object arg0, Object arg1) {
+            Int2 pos0 = ((Int2) arg0);
+            Int2 pos1 = ((Int2) arg1);
+            if (pos0.b() < pos1.b()) {
+                return 1;
+            } else if (pos0.b() > pos1.b()) {
+                return -1;
+            } else {
+                if (pos0.e() < pos1.e()) {
+                    return -1;
+                } else if (pos0.e() > pos1.e()) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        }
+    }
+
+    /**
+     * Maps text position to EObject.
+     */
+    protected Map pos2TemplateElement = new TreeMap(new InversePosComparator());
+
+    /**
+     * Maps TemplateElement to text position.
+     */
+    protected Map template2Positions = new HashMap();
+
+    /**
+     * Maps TemplateElement to comment text position.
+     */
+    protected Map template2CommentPositions = new HashMap();
+
+    /**
+     * Maps text position to an TemplateElement declaration. It is used for an
+     * open link action.
+     */
+    protected Map pos2LinkTemplateElement = new TreeMap(new Comparator() {
+        public int compare(Object arg0, Object arg1) {
+            Int2 pos0 = ((Int2) arg0);
+            Int2 pos1 = ((Int2) arg1);
+            if (pos0.b() < pos1.b()) {
+                return 1;
+            } else if (pos0.b() > pos1.b()) {
+                return -1;
+            } else {
+                if (pos0.e() < pos1.e()) {
+                    return -1;
+                } else if (pos0.e() > pos1.e()) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        }
+    });
+
+    /**
+     * Highlight positions.
+     * <p>
+     * <li>highlightedPos[HIGHLIGHTED_STATIC_TEXT] is a list of positions for
+     * the text which is not in the models.</li>
+     * <li>highlightedPos[HIGHLIGHTED_COMMENT] is a list of positions for
+     * comments.</li>
+     */
+    protected List[] highlightedPos = new List[2];
+
+    // Default highlight.
+    public static final int HIGHLIGHTED_DEFAULT = -1;
+
+    // Highlight for the text which is not in the models.
+    public static final int HIGHLIGHTED_STATIC_TEXT = 0;
+
+    // Highlight for comments.
+    public static final int HIGHLIGHTED_COMMENT = 1;
+
+    /**
+     * Default template for text mapping.
+     */
+    protected TemplateElement template;
+
+    /**
+     * Current size of the text used for the mapping.
+     */
+    protected int shift;
+
+    /**
+     * Indicates if the changes were validated.
+     * <p>
+     * It is impossible to change mappings when commit is true.
+     */
+    protected boolean commit = false;
+
+    /**
+     * Constructor.
+     * 
+     * @param template
+     *            is the default template for text mapping
+     * @param freeze
+     *            is used to freeze the mappings, this helps to improve the
+     *            performance
+     */
+    public TextTemplateElementMapping(TemplateElement template, boolean freeze) {
+        this.template = template;
+        for (int i = 0; i < highlightedPos.length; i++) {
+            if (highlightedPos[i] == null) {
+                highlightedPos[i] = new ArrayList();
+            }
+        }
+        if (freeze) {
+            commit = true;
+        } else {
+            reset();
+        }
+    }
+
+    /**
+     * Reset all informations.
+     */
+    protected void reset() {
+        if (!commit) {
+            this.shift = 0;
+            pos2TemplateElement.clear();
+            index2TemplateElement.clear();
+            template2Positions.clear();
+            template2CommentPositions.clear();
+            pos2LinkTemplateElement.clear();
+            index2LinkTemplateElement.clear();
+            for (int i = 0; i < highlightedPos.length; i++) {
+                if (highlightedPos[i] != null) {
+                    highlightedPos[i].clear();
+                } else {
+                    highlightedPos[i] = new ArrayList();
+                }
+            }
+        }
+    }
+
+    /**
+     * Appends other mappings to current mappings.
+     * 
+     * @param other
+     *            is the other mappings between the model and the text value
+     */
+    public void from(TextTemplateElementMapping other) {
+        if (!commit && other != null) {
+            // mapping pos2TemplateElement, template2Pos
+            Iterator it = other.pos2TemplateElement.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = shift + ((Int2) entry.getKey()).b();
+                int e = shift + ((Int2) entry.getKey()).e();
+                TemplateElement template = (TemplateElement) entry.getValue();
+                addMapping(template, b, e);
+            }
+            // mapping template2CommentPositions
+            it = other.template2CommentPositions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    int b = shift + pos.b();
+                    int e = shift + pos.e();
+                    TemplateElement template = (TemplateElement) entry.getKey();
+                    addCommentMapping(template, b, e);
+                }
+            }
+            // mapping pos2LinkTemplateElement
+            it = other.pos2LinkTemplateElement.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = shift + ((Int2) entry.getKey()).b();
+                int e = shift + ((Int2) entry.getKey()).e();
+                TemplateElement template = (TemplateElement) entry.getValue();
+                pos2LinkTemplateElement.put(new Int2(b, e), template);
+            }
+            // highlightedPos
+            for (int i = 0; i < other.highlightedPos.length; i++) {
+                it = other.highlightedPos[i].iterator();
+                while (it.hasNext()) {
+                    Int2 pos = (Int2) it.next();
+                    highlightedPos[i].add(new Int2(shift + pos.b(), shift + pos.e()));
+                }
+            }
+            // shift
+            shift += other.shift;
+        }
+    }
+
+    /**
+     * Shifts text positions used for the mapping and puts the default
+     * highlight.
+     * 
+     * @param size
+     *            is the size of the shift
+     */
+    public void shift(int size) {
+        shift(size, TextTemplateElementMapping.HIGHLIGHTED_DEFAULT);
+    }
+
+    /**
+     * Shifts text positions used for the mapping and puts the given highlight.
+     * 
+     * @param size
+     *            is the size of the shift
+     * @param highlightedType
+     *            is the text highlight
+     */
+    public void shift(int size, int highlightedType) {
+        if (!commit) {
+            if (linkTemplateElement != null) {
+                Int2 pos = new Int2(shift, shift + size);
+                pos2LinkTemplateElement.put(pos, linkTemplateElement);
+            }
+            if (highlightedType == TextTemplateElementMapping.HIGHLIGHTED_STATIC_TEXT) {
+                Int2 pos = new Int2(shift, shift + size);
+                highlightedPos[TextTemplateElementMapping.HIGHLIGHTED_STATIC_TEXT].add(pos);
+            } else if (highlightedType == TextTemplateElementMapping.HIGHLIGHTED_COMMENT) {
+                Int2 pos = new Int2(shift, shift + size);
+                highlightedPos[TextTemplateElementMapping.HIGHLIGHTED_COMMENT].add(pos);
+                addCommentMapping(template, pos.b(), pos.e());
+            }
+            shift += size;
+        }
+    }
+
+    /**
+     * Adds a mapping between the template and the text begins at the specified
+     * begin and extends to the character at index end - 1.
+     * 
+     * @param template
+     *            is the template element
+     * @param begin
+     *            is the beginning index, inclusive
+     * @param end
+     *            is the ending index, exclusive
+     */
+    protected void addMapping(TemplateElement template, int begin, int end) {
+        if (begin > -1 && end > -1) {
+            // Mapping pos2TemplateElement
+            Int2 newPos = new Int2(begin, end);
+            if (!pos2TemplateElement.containsKey(newPos)) {
+                pos2TemplateElement.put(newPos, template);
+            }
+            // Mapping template2Pos
+            List templatePositions = (List) template2Positions.get(template);
+            if (templatePositions == null) {
+                templatePositions = new ArrayList();
+                template2Positions.put(template, templatePositions);
+            }
+            add(templatePositions, begin, end);
+        }
+    }
+
+    /**
+     * Adds a comment mapping between the template and the text begins at the
+     * specified begin and extends to the character at index end - 1.
+     * 
+     * @param template
+     *            is the template
+     * @param begin
+     *            is the beginning index, inclusive
+     * @param end
+     *            is the ending index, exclusive
+     */
+    protected void addCommentMapping(TemplateElement template, int begin, int end) {
+        if (begin > -1 && end > -1) {
+            List commentPositions = (List) template2CommentPositions.get(template);
+            if (commentPositions == null) {
+                commentPositions = new ArrayList();
+                template2CommentPositions.put(template, commentPositions);
+            }
+            add(commentPositions, begin, end);
+        }
+    }
+
+    /**
+     * Amalgamates the new position and the other positions.
+     * 
+     * @param positions
+     *            is the list of positions
+     * @param begin
+     *            is the beginning index of the new position, inclusive
+     * @param end
+     *            is the ending index of the new position, exclusive
+     */
+    private void add(List positions, int begin, int end) {
+        boolean insert = false;
+        Iterator it = positions.iterator();
+        while (!insert && it.hasNext()) {
+            Int2 pos = (Int2) it.next();
+            if (begin <= pos.e() && begin >= pos.b()) {
+                if (end > pos.e()) {
+                    positions.remove(pos);
+                    add(positions, pos.b(), end);
+                }
+                insert = true;
+            } else if (end >= pos.b() && end <= pos.e()) {
+                if (begin < pos.b()) {
+                    positions.remove(pos);
+                    add(positions, begin, pos.e());
+                }
+                insert = true;
+            } else if (begin < pos.b() && end > pos.e()) {
+                positions.remove(pos);
+                add(positions, begin, end);
+                insert = true;
+            }
+        }
+        if (!insert) {
+            positions.add(new Int2(begin, end));
+        }
+    }
+
+    /**
+     * Marks the begin of an open link action.
+     * 
+     * @param linkTemplateElement
+     *            is the linked template
+     */
+    public void linkBegin(TemplateElement linkTemplateElement) {
+        this.linkTemplateElement = linkTemplateElement;
+    }
+
+    /**
+     * Marks the end of the current open link action.
+     */
+    public void linkEnd() {
+        this.linkTemplateElement = null;
+    }
+
+    /**
+     * Open link result for the next added text
+     */
+    protected TemplateElement linkTemplateElement = null;
+
+    /**
+     * Validate the changes.
+     * <p>
+     * It is impossible to change mappings now.
+     */
+    protected void commit() {
+        if (!commit) {
+            commit = true;
+            addMapping(template, 0, shift);
+        }
+    }
+
+    /**
+     * Returns the template at the given index.
+     * 
+     * @param index
+     *            is the position in the text
+     * @return the template at the index.
+     */
+    public TemplateElement index2TemplateElement(int index) {
+        TemplateElement template = (TemplateElement) index2TemplateElement.get(new Integer(index));
+        if (template == null) {
+            if (!commit) {
+                commit();
+            }
+            Iterator it = pos2TemplateElement.entrySet().iterator();
+            while (template == null && it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = ((Int2) entry.getKey()).b();
+                if (index >= b) {
+                    int e = ((Int2) entry.getKey()).e();
+                    if (index < e) {
+                        template = (TemplateElement) entry.getValue();
+                    }
+                }
+            }
+            index2TemplateElement.put(new Integer(index), template);
+        }
+        return template;
+    }
+
+    private Map index2TemplateElement = new HashMap();
+
+    /**
+     * Gets a serializable template that maps the ranges of the text and the
+     * URIs of the templates.
+     * 
+     * @return a serializable map
+     * @deprecated
+     */
+    @Deprecated
+    public Map position2uriSerializableMap() {
+        Map result = new TreeMap(new InversePosComparator());
+        if (!commit) {
+            commit();
+        }
+        Iterator it = pos2TemplateElement.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            Int2 pos = (Int2) entry.getKey();
+            TemplateElement template = (TemplateElement) entry.getValue();
+            String uriFragment = template.getURIFragment();
+            result.put(pos, uriFragment);
+        }
+        return result;
+    }
+
+    /**
+     * Returns the positions of the given template.
+     * 
+     * @param template
+     *            is the template
+     * @return the positions of the template
+     */
+    public Int2[] template2Positions(TemplateElement template) {
+        if (template == null) {
+            return new Int2[] {};
+        }
+        if (!commit) {
+            commit();
+        }
+        List positions = (List) template2Positions.get(template);
+        if (positions != null) {
+            return (Int2[]) positions.toArray(new Int2[positions.size()]);
+        } else {
+            return new Int2[] {};
+        }
+    }
+
+    /**
+     * Gets a serializable template that maps the URIs of the templates and the
+     * ranges of the text.
+     * 
+     * @return a serializable map
+     * @deprecated
+     */
+    @Deprecated
+    public Map uri2positionsSerializableMap() {
+        Map result = new TreeMap(new StringComparator());
+        if (!commit) {
+            commit();
+        }
+        Iterator entries = template2Positions.entrySet().iterator();
+        while (entries.hasNext()) {
+            Map.Entry entry = (Map.Entry) entries.next();
+            TemplateElement template = (TemplateElement) entry.getKey();
+            String uriFragment = template.getURIFragment();
+            Set positions = new TreeSet(new Comparator() {
+                public int compare(Object arg0, Object arg1) {
+                    Int2 pos0 = ((Int2) arg0);
+                    Int2 pos1 = ((Int2) arg1);
+                    if (pos0.b() < pos1.b()) {
+                        return -1;
+                    } else if (pos0.b() > pos1.b()) {
+                        return 1;
+                    } else {
+                        if (pos0.e() < pos1.e()) {
+                            return 1;
+                        } else if (pos0.e() > pos1.e()) {
+                            return -1;
+                        } else {
+                            return 0;
+                        }
+                    }
+                }
+            });
+            positions.addAll((List) entry.getValue());
+            result.put(uriFragment, positions.toArray(new Int2[positions.size()]));
+        }
+        return result;
+    }
+
+    /**
+     * Returns the first comment position of the given template.
+     * 
+     * @param template
+     *            is the template
+     * @param limits
+     *            delimits the part of the text where the comment can be
+     *            searched
+     * @return the first comment position of the template
+     */
+    public Int2 template2CommentPositionIn(TemplateElement template, Int2 limits) {
+        if (template == null) {
+            return Int2.NOT_FOUND;
+        }
+        if (!commit) {
+            commit();
+        }
+        List positions = (List) template2CommentPositions.get(template);
+        if (positions != null) {
+            Iterator it = positions.iterator();
+            while (it.hasNext()) {
+                Int2 pos = (Int2) it.next();
+                if (pos.b() >= limits.b() && pos.e() <= limits.e()) {
+                    return pos;
+                }
+            }
+        }
+        return Int2.NOT_FOUND;
+    }
+
+    /**
+     * Returns the linked template at the given index. It is used to make an
+     * open link action.
+     * 
+     * @param index
+     *            is the position in the text
+     * @return the linked template at the index
+     */
+    public TemplateElement index2LinkTemplateElement(int index) {
+        TemplateElement template = (TemplateElement) index2LinkTemplateElement.get(new Integer(index));
+        if (template == null) {
+            if (!commit) {
+                commit();
+            }
+            Iterator it = pos2LinkTemplateElement.entrySet().iterator();
+            while (template == null && it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                int b = ((Int2) entry.getKey()).b();
+                if (index >= b) {
+                    int e = ((Int2) entry.getKey()).e();
+                    if (index < e) {
+                        template = (TemplateElement) entry.getValue();
+                    }
+                }
+            }
+            index2LinkTemplateElement.put(new Integer(index), template);
+        }
+        return template;
+    }
+
+    private Map index2LinkTemplateElement = new HashMap();
+
+    /**
+     * Returns all positions for the given highlight.
+     * 
+     * @param highlightedType
+     *            is the text highlight
+     * @return all positions for the given highlight
+     */
+    public Int2[] getHighlightedPos(int highlightedType) {
+        if (highlightedType == TextTemplateElementMapping.HIGHLIGHTED_STATIC_TEXT) {
+            return (Int2[]) highlightedPos[TextTemplateElementMapping.HIGHLIGHTED_STATIC_TEXT].toArray(new Int2[] {});
+        } else if (highlightedType == TextTemplateElementMapping.HIGHLIGHTED_COMMENT) {
+            return (Int2[]) highlightedPos[TextTemplateElementMapping.HIGHLIGHTED_COMMENT].toArray(new Int2[] {});
+        } else {
+            return new Int2[] {};
+        }
+    }
+
+    /**
+     * Moves the bounds of the errors into the given range
+     * 
+     * @param range
+     *            are the new bounds
+     */
+    public void range(Int2 range) {
+        if (!commit) {
+            shift = range.e() - range.b();
+            // mapping pos2TemplateElement
+            Iterator it = pos2TemplateElement.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                Int2 pos = (Int2) entry.getKey();
+                Int2 copy = new Int2(pos.b(), pos.e());
+                copy.range(range);
+                if (copy.b() == -1 || (!copy.equals(pos) && pos2TemplateElement.containsKey(copy))) {
+                    it.remove();
+                } else {
+                    pos.range(range);
+                }
+            }
+            // mapping template2Positions
+            it = template2Positions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.range(range);
+                    if (pos.b() == -1) {
+                        positions.remove();
+                    }
+                }
+            }
+            // mapping template2CommentPositions
+            it = template2CommentPositions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.range(range);
+                    if (pos.b() == -1) {
+                        positions.remove();
+                    }
+                }
+            }
+            // mapping pos2LinkTemplateElement
+            it = pos2LinkTemplateElement.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                Int2 pos = (Int2) entry.getKey();
+                Int2 copy = new Int2(pos.b(), pos.e());
+                copy.range(range);
+                if (copy.b() == -1 || (!copy.equals(pos) && pos2LinkTemplateElement.containsKey(copy))) {
+                    it.remove();
+                } else {
+                    pos.range(range);
+                }
+            }
+            // highlightedPos
+            for (List highlightedPo : highlightedPos) {
+                it = highlightedPo.iterator();
+                while (it.hasNext()) {
+                    Int2 pos = (Int2) it.next();
+                    pos.range(range);
+                    if (pos.b() == -1) {
+                        it.remove();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Applies the indent strategy to the positions (each line adds one
+     * character).
+     * 
+     * @param lines
+     *            are the positions of the lines
+     */
+    public void indent(Int2[] lines) {
+        if (!commit) {
+            shift += lines.length;
+            // mapping pos2TemplateElement
+            Iterator it = pos2TemplateElement.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                ((Int2) entry.getKey()).indent(lines);
+            }
+            // mapping template2Positions
+            it = template2Positions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.indent(lines);
+                }
+            }
+            // mapping template2CommentPositions
+            it = template2CommentPositions.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                List value = (List) entry.getValue();
+                Iterator positions = value.iterator();
+                while (positions.hasNext()) {
+                    Int2 pos = (Int2) positions.next();
+                    pos.indent(lines);
+                }
+            }
+            // mapping pos2LinkTemplateElement
+            it = pos2LinkTemplateElement.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry entry = (Map.Entry) it.next();
+                ((Int2) entry.getKey()).indent(lines);
+            }
+            // highlightedPos
+            for (List highlightedPo : highlightedPos) {
+                it = highlightedPo.iterator();
+                while (it.hasNext()) {
+                    Int2 pos = (Int2) it.next();
+                    pos.indent(lines);
+                }
+            }
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/log/EvalFailure.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/log/EvalFailure.java
new file mode 100644
index 0000000..00ad547
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/log/EvalFailure.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval.log;
+
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.tools.log.IFailure;
+
+/**
+ * Template evaluation failures.
+ * 
+ * 
+ */
+public class EvalFailure implements IFailure {
+
+    /**
+     * Failure message.
+     */
+    protected String message;
+
+    /**
+     * Position in the generated text.
+     */
+    protected int position = 0;
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the failure message
+     */
+    public EvalFailure(String message) {
+        this.message = message;
+    }
+
+    /* (non-Javadoc) */
+    public String getMessage() {
+        return AcceleoGenMessages.getString("EvalFailure.FailureMessage", new Object[] { message, }); //$NON-NLS-1$
+    }
+
+    /* (non-Javadoc) */
+    public int position() {
+        return position;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return AcceleoGenMessages.getString("EvalFailure.FailurePosition", new Object[] { Integer.toString(position()), }) + " : " + getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/log/EvalLog.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/log/EvalLog.java
new file mode 100644
index 0000000..0b33ac8
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/log/EvalLog.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval.log;
+
+import java.util.Iterator;
+
+import org.eclipse.sirius.query.legacy.tools.log.TreeLog;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * Template log that contains evaluation failures.
+ * 
+ * 
+ */
+public class EvalLog extends TreeLog {
+
+    /**
+     * Constructor.
+     */
+    public EvalLog() {
+        super();
+    }
+
+    /**
+     * Constructor with one failure.
+     * 
+     * @param failure
+     *            is the first failure
+     */
+    public EvalLog(EvalFailure failure) {
+        super(failure);
+    }
+
+    /**
+     * Add evaluation error.
+     * 
+     * @param failure
+     *            is a new failure
+     */
+    public void addError(EvalFailure failure) {
+        super.addError(failure);
+    }
+
+    /**
+     * Add evaluation warning.
+     * 
+     * @param failure
+     *            is a new failure
+     */
+    public void addSevereWarning(EvalFailure failure) {
+        super.addSevereWarning(failure);
+    }
+
+    /**
+     * Shift position in generated text for all failures.
+     * 
+     * @param shift
+     *            is the size of the shift
+     */
+    public void shiftPosition(int shift) {
+        Iterator errors = this.errors.iterator();
+        while (errors.hasNext()) {
+            EvalFailure failure = (EvalFailure) errors.next();
+            failure.position += shift;
+        }
+        Iterator severeWarnings = this.severeWarnings.iterator();
+        while (severeWarnings.hasNext()) {
+            EvalFailure failure = (EvalFailure) severeWarnings.next();
+            failure.position += shift;
+        }
+    }
+
+    /**
+     * Moves the bounds of the errors into the given range
+     * 
+     * @param range
+     *            are the new bounds
+     */
+    public void range(Int2 range) {
+        if (range.b() > -1 && range.e() > -1) {
+            Iterator errors = this.errors.iterator();
+            while (errors.hasNext()) {
+                EvalFailure failure = (EvalFailure) errors.next();
+                if (failure.position > range.e()) {
+                    errors.remove();
+                } else {
+                    failure.position -= range.b();
+                }
+            }
+            Iterator severeWarnings = this.severeWarnings.iterator();
+            while (severeWarnings.hasNext()) {
+                EvalFailure failure = (EvalFailure) severeWarnings.next();
+                if (failure.position > range.e()) {
+                    errors.remove();
+                } else {
+                    failure.position -= range.b();
+                }
+            }
+        }
+    }
+
+    /**
+     * Applies the indent strategy to the positions (each line adds one
+     * character).
+     * 
+     * @param lines
+     *            are the positions of the lines
+     */
+    public void indent(Int2[] lines) {
+        for (Int2 line : lines) {
+            Iterator errors = this.errors.iterator();
+            while (errors.hasNext()) {
+                EvalFailure failure = (EvalFailure) errors.next();
+                if (line.b() < failure.position) {
+                    failure.position++;
+                }
+            }
+            Iterator severeWarnings = this.severeWarnings.iterator();
+            while (severeWarnings.hasNext()) {
+                EvalFailure failure = (EvalFailure) severeWarnings.next();
+                if (line.b() < failure.position) {
+                    failure.position++;
+                }
+            }
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/merge/MergeTools.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/merge/MergeTools.java
new file mode 100644
index 0000000..71eb59b
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/eval/merge/MergeTools.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.eval.merge;
+
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+
+/**
+ * Round-trip support for templates.
+ * 
+ * 
+ */
+public class MergeTools {
+
+    /**
+     * Default tag used to start the user code.
+     */
+    public static final String DEFAULT_USER_BEGIN = AcceleoGenMessages.getString("MergeTools.UserCodeStart"); //$NON-NLS-1$
+
+    /**
+     * Default tag used to stop the user code.
+     */
+    public static final String DEFAULT_USER_END = AcceleoGenMessages.getString("MergeTools.UserCodeEnd"); //$NON-NLS-1$
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/ExpressionTools.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/ExpressionTools.java
new file mode 100644
index 0000000..eec5dc7
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/ExpressionTools.java
@@ -0,0 +1,486 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * Expression evaluation tools. It evaluates ENode expressions.
+ * <p>
+ * Samples : || , && , == , != , + , - , / , * , > , >= , < , <=
+ * 
+ * @see ENode
+ */
+public class ExpressionTools {
+
+    /**
+     * Evaluates an expression '||' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode or(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isList()) {
+            ENodeList res = new ENodeList();
+            if (e2.isList()) {
+                res.addAll(e1.getList());
+                res.addAll(e2.getList());
+            } else {
+                res.addAll(e1.getList());
+                res.add(e1);
+            }
+            return new ENode(res, e1);
+        } else if (e1.isBoolean() && e2.isBoolean()) {
+            return new ENode(e1.getBoolean() || e2.getBoolean(), e1);
+        } else {
+            return new ENode(((Boolean) e1.getAdapterValue(boolean.class)).booleanValue() || ((Boolean) e2.getAdapterValue(boolean.class)).booleanValue(), e1);
+        }
+    }
+
+    /**
+     * Evaluates an expression '&&' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode and(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isList()) {
+            ENodeList res = new ENodeList();
+            if (e2.isList()) {
+                ENodeIterator it = e1.getList().iterator();
+                while (it.hasNext()) {
+                    ENode n1 = it.next();
+                    if (e2.getList().contains(n1)) {
+                        res.add(n1);
+                    }
+                }
+            } else {
+                ENodeIterator it = e1.getList().iterator();
+                while (it.hasNext()) {
+                    ENode n1 = it.next();
+                    if (e2.equals(n1)) {
+                        res.add(n1);
+                    }
+                }
+            }
+            return new ENode(res, e1);
+        } else if (e1.isBoolean() && e2.isBoolean()) {
+            return new ENode(e1.getBoolean() && e2.getBoolean(), e1);
+        } else {
+            return new ENode(((Boolean) e1.getAdapterValue(boolean.class)).booleanValue() && ((Boolean) e2.getAdapterValue(boolean.class)).booleanValue(), e1);
+        }
+    }
+
+    /**
+     * Evaluates an expression '==' between two nodes.
+     * <p>
+     * Returns e1.equals(e2)
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     *             if the types of the nodes are not compatible
+     */
+    public static ENode equals(ENode e1, ENode e2) throws ENodeCastException {
+        return new ENode(e1.equals(e2), e1);
+    }
+
+    /**
+     * Evaluates an expression '!=' between two nodes.
+     * <p>
+     * Returns !e1.equals(e2)
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     *             if the types of the nodes are not compatible
+     */
+    public static ENode notEquals(ENode e1, ENode e2) throws ENodeCastException {
+        return new ENode(!e1.equals(e2), e1);
+    }
+
+    /**
+     * Evaluates an expression '+' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode add(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isList()) {
+            ENodeList res = new ENodeList();
+            if (e2.isList()) {
+                res.addAll(e1.getList());
+                res.addAll(e2.getList());
+            } else {
+                res.addAll(e1.getList());
+                res.add(e2);
+            }
+            return new ENode(res, e1);
+        } else if (e2.isList()) {
+            ENodeList res = new ENodeList();
+            res.add(e1);
+            res.addAll(e2.getList());
+            return new ENode(res, e1);
+        } else if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() + e2.getInt(), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() + e2.getDouble(), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() + e2.getInt(), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() + e2.getDouble(), e1);
+        } else if (e1.isString() || e2.isString()) {
+            ENode result = new ENode("", e1); //$NON-NLS-1$
+            result.append(e1);
+            result.append(e2);
+            return result;
+        } else if (e1.isNull()) {
+            return e2;
+        } else if (e2.isNull()) {
+            return e1;
+        } else {
+            ENodeList res = new ENodeList();
+            res.add(e1);
+            res.add(e2);
+            return new ENode(res, e1);
+        }
+    }
+
+    /**
+     * Evaluates an expression '-' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode sub(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isList()) {
+            ENodeList res = new ENodeList();
+            res.addAll(e1.getList());
+            if (e2.isList()) {
+                ENodeIterator it = e2.getList().iterator();
+                while (it.hasNext()) {
+                    ENode n2 = it.next();
+                    res.remove(n2);
+                }
+            } else {
+                res.remove(e2);
+            }
+            return new ENode(res, e1);
+        } else if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() - e2.getInt(), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() - e2.getDouble(), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() - e2.getInt(), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() - e2.getDouble(), e1);
+        } else if (e1.isNull()) {
+            return e1;
+        } else if (e2.isNull()) {
+            return e1;
+        } else if (e1.isString()) {
+            Int2[] positions = TextSearch.getDefaultSearch().allIndexOf(e1.getString(), e2.toString());
+            if (positions.length == 0) {
+                return e1;
+            } else {
+                String s1 = e1.getString();
+                StringBuffer result = new StringBuffer(s1.substring(0, positions[0].b()));
+                for (int i = 1; i < positions.length; i++) {
+                    result.append(s1.substring(positions[i - 1].e(), positions[i].b()));
+                }
+                result.append(s1.substring(positions[positions.length - 1].e(), s1.length()));
+                return new ENode(result.toString(), e1);
+            }
+        } else if (e1.isEObject()) {
+            if (e1.equals(e2)) {
+                return new ENode(ENode.EMPTY, e1);
+            } else {
+                return e1;
+            }
+        }
+        final String expression = e1.getType() + ' ' + TemplateConstants.OPERATOR_SUB + ' ' + e2.getType();
+        throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.InvalidExpression", new Object[] { expression, })); //$NON-NLS-1$
+    }
+
+    /**
+     * Evaluates an expression '/' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode div(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() / ExpressionTools.div0(e2.getInt()), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() / ExpressionTools.div0(e2.getDouble()), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() / ExpressionTools.div0(e2.getInt()), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() / ExpressionTools.div0(e2.getDouble()), e1);
+        } else {
+            try {
+                // adapter "int / int"
+                if (e2.isInt() || (e2.isString() && e2.getString().indexOf(".") == -1)) { //$NON-NLS-1$
+                    return new ENode(((Integer) e1.getAdapterValue(int.class)).intValue() / ExpressionTools.div0(((Integer) e2.getAdapterValue(int.class)).intValue()), e1);
+                }
+            } catch (ENodeCastException ex1) {
+                // step
+            }
+            try {
+                // adapter "double / double" (it includes "int / double" and
+                // "double / int")
+                if (e2.isDouble() || e2.isString()) {
+                    return new ENode(((Double) e1.getAdapterValue(double.class)).doubleValue() / ExpressionTools.div0(((Double) e2.getAdapterValue(double.class)).doubleValue()), e1);
+                }
+            } catch (ENodeCastException ex2) {
+                // step
+            }
+            final String expression = e1.getType() + ' ' + TemplateConstants.OPERATOR_DIV + ' ' + e2.getType();
+            throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.InvalidExpression", new Object[] { expression, })); //$NON-NLS-1$
+        }
+    }
+
+    private static int div0(int i) throws ENodeCastException {
+        if (i == 0) {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.ZeroDivide")); //$NON-NLS-1$
+        }
+        return i;
+    }
+
+    private static double div0(double d) throws ENodeCastException {
+        if (d == 0) {
+            throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.ZeroDivide")); //$NON-NLS-1$
+        }
+        return d;
+    }
+
+    /**
+     * Evaluates an expression '*' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode mul(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() * e2.getInt(), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() * e2.getDouble(), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() * e2.getInt(), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() * e2.getDouble(), e1);
+        } else {
+            try {
+                // adapter "int * int"
+                if ((e1.isInt() || (e1.isString() && e1.getString().indexOf(".") == -1)) && (e2.isInt() || (e2.isString() && e2.getString().indexOf(".") == -1))) { //$NON-NLS-1$ //$NON-NLS-2$
+                    return new ENode(((Integer) e1.getAdapterValue(int.class)).intValue() * ((Integer) e2.getAdapterValue(int.class)).intValue(), e1);
+                }
+            } catch (ENodeCastException ex1) {
+                // step
+            }
+            try {
+                // adapter "double * double" (it includes "int * double" and
+                // "double * int")
+                if ((e1.isDouble() || e1.isString()) && (e2.isDouble() || e2.isString())) {
+                    return new ENode(((Double) e1.getAdapterValue(double.class)).doubleValue() * ((Double) e2.getAdapterValue(double.class)).doubleValue(), e1);
+                }
+            } catch (ENodeCastException ex2) {
+                // step
+            }
+            final String expression = e1.getType() + ' ' + TemplateConstants.OPERATOR_MUL + ' ' + e2.getType();
+            throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.InvalidExpression", new Object[] { expression, })); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Evaluates an expression '>' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode sup(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() > e2.getInt(), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() > e2.getDouble(), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() > e2.getInt(), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() > e2.getDouble(), e1);
+        } else if (e1.isString() && e2.isString()) {
+            return new ENode(e1.getString().compareTo(e2.getString()) > 0, e1);
+        } else {
+            try {
+                // adapter "double > double" (it includes "int > double" and
+                // "double > int")
+                return new ENode(((Double) e1.getAdapterValue(double.class)).doubleValue() > ((Double) e2.getAdapterValue(double.class)).doubleValue(), e1);
+            } catch (ENodeCastException ex) {
+                final String expression = e1.toString() + '>' + e2.toString() + " [" + e1.getType() + '>' + e2.getType() + ']'; //$NON-NLS-1$
+                throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.AdapterNotFound", new Object[] { ">", expression, })); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+        }
+    }
+
+    /**
+     * Evaluates an expression '>=' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode supE(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() >= e2.getInt(), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() >= e2.getDouble(), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() >= e2.getInt(), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() >= e2.getDouble(), e1);
+        } else if (e1.isString() && e2.isString()) {
+            return new ENode(e1.getString().compareTo(e2.getString()) >= 0, e1);
+        } else {
+            try {
+                // adapter "double >= double" (it includes "int >= double"
+                // and "double >= int")
+                return new ENode(((Double) e1.getAdapterValue(double.class)).doubleValue() >= ((Double) e2.getAdapterValue(double.class)).doubleValue(), e1);
+            } catch (ENodeCastException ex) {
+                final String expression = e1.toString() + ">=" + e2.toString() + " [" + e1.getType() + ">=" + e2.getType() + ']'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.AdapterNotFound", new Object[] { ">=", expression, })); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+        }
+    }
+
+/**
+	 * Evaluates an expression '<' between two nodes.
+	 * <p>
+	 * 
+	 * @param e1
+	 *            is the first node
+	 * @param e2
+	 *            is the second node
+	 * @return the result node
+	 * @throws ENodeCastException
+	 */
+    public static ENode inf(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() < e2.getInt(), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() < e2.getDouble(), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() < e2.getInt(), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() < e2.getDouble(), e1);
+        } else if (e1.isString() && e2.isString()) {
+            return new ENode(e1.getString().compareTo(e2.getString()) < 0, e1);
+        } else {
+            try {
+                // adapter "double < double" (it includes "int < double" and
+                // "double < int")
+                return new ENode(((Double) e1.getAdapterValue(double.class)).doubleValue() < ((Double) e2.getAdapterValue(double.class)).doubleValue(), e1);
+            } catch (ENodeCastException ex) {
+                final String expression = e1.toString() + '<' + e2.toString() + " [" + e1.getType() + '<' + e2.getType() + ']'; //$NON-NLS-1$
+                throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.AdapterNotFound", new Object[] { "<", expression, })); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+        }
+    }
+
+    /**
+     * Evaluates an expression '<=' between two nodes.
+     * <p>
+     * 
+     * @param e1
+     *            is the first node
+     * @param e2
+     *            is the second node
+     * @return the result node
+     * @throws ENodeCastException
+     */
+    public static ENode infE(ENode e1, ENode e2) throws ENodeCastException {
+        if (e1.isInt() && e2.isInt()) {
+            return new ENode(e1.getInt() <= e2.getInt(), e1);
+        } else if (e1.isDouble() && e2.isDouble()) {
+            return new ENode(e1.getDouble() <= e2.getDouble(), e1);
+        } else if (e1.isDouble() && e2.isInt()) {
+            return new ENode(e1.getDouble() <= e2.getInt(), e1);
+        } else if (e1.isInt() && e2.isDouble()) {
+            return new ENode(e1.getInt() <= e2.getDouble(), e1);
+        } else if (e1.isString() && e2.isString()) {
+            return new ENode(e1.getString().compareTo(e2.getString()) <= 0, e1);
+        } else {
+            try {
+                // adapter "double <= double" (it includes "int <= double"
+                // and "double <= int")
+                return new ENode(((Double) e1.getAdapterValue(double.class)).doubleValue() <= ((Double) e2.getAdapterValue(double.class)).doubleValue(), e1);
+            } catch (ENodeCastException ex) {
+                final String expression = e1.toString() + "<=" + e2.toString() + " [" + e1.getType() + "<=" + e2.getType() + ']'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                throw new ENodeCastException(AcceleoGenMessages.getString("ExpressionTools.AdapterNotFound", new Object[] { "<=", expression, })); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateCallExpression.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateCallExpression.java
new file mode 100644
index 0000000..2e6e994
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateCallExpression.java
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * This is a variable call expression for the generation tool. It is a kind of
+ * expression. A variable call can be a link of the model or a java service.
+ * Between the brackets after a java service name, there is a list of arguments.
+ * Each argument is an expression. The argument list is a sequence of entries,
+ * each separated from the next by a comma. Syntactically, a service call
+ * expression is an open parenthesis followed by one or more expressions
+ * followed by a close parenthesis. The remaining expressions are all evaluated
+ * and their values are the arguments to the service.
+ * 
+ * 
+ */
+public class TemplateCallExpression extends TemplateExpression {
+
+    /**
+     * The called link that is a template, a link of the model or a java service
+     * name.
+     */
+    protected String link;
+
+    /**
+     * The prefix to filter a template, a link of the model or a java service.
+     */
+    protected String prefix;
+
+    /**
+     * Between the parenthesis after a java service name or a template name,
+     * there is a list of arguments. Each argument is an expression. The
+     * remaining expressions are all evaluated and their values are the
+     * arguments to the service.
+     */
+    protected List arguments = new ArrayList();
+
+    /**
+     * Between the brackets after a java service name or a template name, there
+     * is a filter.
+     */
+    protected TemplateExpression filter = null;
+
+    /**
+     * It's the next variable call expression for the current statement.
+     */
+    protected TemplateCallExpression nextCall = null;
+
+    /**
+     * Constructor.
+     * 
+     * @param link
+     *            is a link of the model or a java service name
+     * @param script
+     *            is the script
+     */
+    public TemplateCallExpression(String link, IScript script) {
+        super(script);
+        if (link != null) {
+            final int iDot = link.indexOf(TemplateConstants.LINK_PREFIX_SEPARATOR);
+            if (iDot > -1) {
+                this.prefix = link.substring(0, iDot).trim();
+                this.link = link.substring(iDot + TemplateConstants.LINK_PREFIX_SEPARATOR.length()).trim();
+            } else {
+                this.prefix = ""; //$NON-NLS-1$
+                this.link = link.trim();
+            }
+        } else {
+            this.prefix = ""; //$NON-NLS-1$
+            this.link = ""; //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * @return the called link
+     */
+    public String getLink() {
+        return link;
+    }
+
+    /**
+     * @return the prefix
+     */
+    public String getPrefix() {
+        return prefix;
+    }
+
+    /**
+     * @return the next variable call expression for the current statement
+     */
+    public TemplateCallExpression getNextCall() {
+        return nextCall;
+    }
+
+    /**
+     * @param next
+     *            is the next variable call expression for the current statement
+     */
+    public void setNextCall(TemplateCallExpression nextCall) {
+        this.nextCall = nextCall;
+    }
+
+    /**
+     * @return the arguments
+     */
+    public List getArguments() {
+        return arguments;
+    }
+
+    /**
+     * @return the filter
+     */
+    public TemplateExpression getFilter() {
+        return filter;
+    }
+
+    /**
+     * @param filter
+     *            is the filter
+     */
+    public void setFilter(TemplateExpression filter) {
+        this.filter = filter;
+        this.filter.setParent(this);
+    }
+
+    /**
+     * Adds an argument expression for the service.
+     * 
+     * @param expression
+     *            is the new argument
+     */
+    public void addArgument(TemplateExpression expression) {
+        arguments.add(expression);
+        expression.setParent(this);
+    }
+
+    /**
+     * Counts the arguments.
+     * 
+     * @return the number of arguments
+     */
+    public int countArguments() {
+        return arguments.size();
+    }
+
+    /**
+     * Gets the first argument.
+     * 
+     * @return the first argument
+     */
+    public TemplateExpression getFirstArgument() {
+        if (arguments.size() > 0) {
+            return (TemplateExpression) arguments.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Now, the next evaluation will be ignored.
+     */
+    public void ignoreNextEval() {
+        ignoreNextEval = true;
+    }
+
+    private boolean ignoreNextEval = false;
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException {
+        ENode result = evaluateSub(current, script, mode);
+        if (filter != null) {
+            result = select(result);
+        }
+        return result;
+    }
+
+    private ENode evaluateSub(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException {
+        // Ignore?
+        if (ignoreNextEval) {
+            ignoreNextEval = false;
+            return current;
+        } else {
+            ENode argCurrent = (ENode) script.contextPeek(IScript.CURRENT_NODE);
+            if (argCurrent == null) {
+                argCurrent = current;
+            }
+            if (link.length() == 0) {
+                if (arguments.size() == 1) {
+                    final TemplateExpression arg = (TemplateExpression) arguments.get(0);
+                    return arg.evaluate(argCurrent, script, mode);
+                } else if (arguments.size() > 1) {
+                    final ENodeList result = new ENodeList();
+                    final Iterator arguments = this.arguments.iterator();
+                    while (arguments.hasNext()) {
+                        final TemplateExpression arg = (TemplateExpression) arguments.next();
+                        final ENode argEval = arg.evaluate(argCurrent, script, mode);
+                        result.add(argEval);
+                    }
+                    return new ENode(result, current);
+                } else {
+                    return new ENode(ENode.EMPTY, current);
+                }
+            } else {
+                // Arguments
+                final List argList = new ArrayList();
+                final Iterator arguments = this.arguments.iterator();
+                while (arguments.hasNext()) {
+                    final TemplateExpression arg = (TemplateExpression) arguments.next();
+                    final ENode argEval = arg.evaluate(argCurrent, script, mode);
+                    argList.add(argEval);
+                }
+                // Call the script or the service
+                final ENode[] args = (ENode[]) argList.toArray(new ENode[argList.size()]);
+                // Specific strategy
+                ENode result = null;
+                final IScript[] specifics = script.goToSpecifics();
+                if (specifics != null && specifics.length > 0) {
+                    ENodeException.disableRuntimeMarkersFor(this);
+                    try {
+                        for (int i = 0; result == null && i < specifics.length; i++) {
+                            final IScript specific = specifics[i];
+                            try {
+                                result = specific.eGet(this, current, args, mode, false);
+                            } catch (final ENodeException e) {
+                                // result = null;
+                            }
+                        }
+                    } finally {
+                        ENodeException.enableRuntimeMarkersFor(this);
+                    }
+                }
+                if (result == null) {
+                    result = script.eGet(this, current, args, mode, true);
+                }
+                if (result == null) {
+                    throw new ENodeException(AcceleoGenMessages.getString("TemplateCallExpression.UnresolvedCall", new Object[] { getLink(), }), pos, script, current, true); //$NON-NLS-1$
+                }
+                return result;
+            }
+        }
+    }
+
+    private ENode select(ENode current) throws FactoryException {
+        // ASSERT filter != null
+        if (current.isList()) {
+            final ENodeList res = new ENodeList();
+            try {
+                final ENodeList list = current.getList();
+                final ENodeIterator it = list.iterator();
+                while (it.hasNext()) {
+                    res.add(select(it.next()));
+                }
+            } catch (final ENodeCastException e) {
+                // Never catch
+            }
+            return new ENode(res, current);
+        } else {
+            script.contextPush(IScript.CURRENT_NODE, current);
+            script.contextPush(IScript.TEMPLATE_NODE, current);
+            try {
+                final ENode result = filter.evaluate(current, script, LaunchManager.create("run", true)); //$NON-NLS-1$
+                final Object boolValue = result.getAdapterValue(boolean.class);
+                if (boolValue instanceof Boolean && ((Boolean) boolValue).booleanValue()) {
+                    return current;
+                } else {
+                    return new ENode(ENode.EMPTY, current);
+                }
+            } catch (final ENodeException e) {
+                return new ENode(ENode.EMPTY, current);
+            } catch (final ENodeCastException e) {
+                return new ENode(ENode.EMPTY, current);
+            } finally {
+                script.contextPop(IScript.CURRENT_NODE);
+                script.contextPop(IScript.TEMPLATE_NODE);
+            }
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        final StringBuffer buffer = new StringBuffer();
+        if (prefix != null && prefix.length() > 0) {
+            buffer.append(prefix);
+            buffer.append(TemplateConstants.LINK_PREFIX_SEPARATOR);
+        }
+        buffer.append(link);
+        if (this.arguments.size() > 0) {
+            buffer.append(TemplateConstants.PARENTH[0]);
+            final Iterator arguments = this.arguments.iterator();
+            while (arguments.hasNext()) {
+                final TemplateExpression argument = (TemplateExpression) arguments.next();
+                buffer.append(argument.toString());
+                if (arguments.hasNext()) {
+                    buffer.append(TemplateConstants.ARG_SEP);
+                }
+            }
+            buffer.append(TemplateConstants.PARENTH[1]);
+        }
+        if (this.filter != null) {
+            buffer.append(TemplateConstants.BRACKETS[0]);
+            buffer.append(this.filter.toString());
+            buffer.append(TemplateConstants.BRACKETS[1]);
+        }
+        return buffer.toString();
+    }
+
+    /* (non-Javadoc) */
+    public static TemplateExpression fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        Int2 trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+        if (trim.b() == -1) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+        } else {
+            limits = trim;
+        }
+        TemplateExpression filter = null;
+        Int2 begin = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.BRACKETS[0], limits.b(), limits.e(), TemplateConstants.SPEC,
+                new String[][] { TemplateConstants.LITERAL, TemplateConstants.PARENTH });
+        if (begin.b() > -1) {
+            final Int2 end = TextSearch.getDefaultSearch().blockIndexEndIn(buffer, TemplateConstants.BRACKETS[0], TemplateConstants.BRACKETS[1], begin.b(), limits.e(), false, TemplateConstants.SPEC,
+                    TemplateConstants.INHIBS_EXPRESSION);
+            if (end.b() == -1) {
+                throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingCloseBracket"), script, begin.b()); //$NON-NLS-1$
+            }
+            if (buffer.substring(end.e(), limits.e()).trim().length() > 0) {
+                throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidSequence"), script, end.e()); //$NON-NLS-1$
+            }
+            final Int2 pos = new Int2(begin.e(), end.b());
+            filter = TemplateExpression.fromString(buffer, pos, script);
+            filter.setPos(pos);
+            limits = new Int2(limits.b(), begin.b());
+            trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+            if (trim.b() == -1) {
+                throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+            } else {
+                limits = trim;
+            }
+        }
+        TemplateCallExpression expression;
+        begin = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.PARENTH[0], limits.b(), limits.e(), TemplateConstants.SPEC, new String[][] { TemplateConstants.LITERAL });
+        if (begin.b() > -1) {
+            final Int2 end = TextSearch.getDefaultSearch().blockIndexEndIn(buffer, TemplateConstants.PARENTH[0], TemplateConstants.PARENTH[1], begin.b(), limits.e(), false, TemplateConstants.SPEC,
+                    TemplateConstants.INHIBS_EXPRESSION);
+            if (end.b() == -1) {
+                throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingCloseParenthesis"), script, begin.b()); //$NON-NLS-1$
+            }
+            if (buffer.substring(end.e(), limits.e()).trim().length() > 0) {
+                throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidSequence"), script, end.e()); //$NON-NLS-1$
+            }
+            final Int2[] positions = TextSearch.getDefaultSearch().splitPositionsIn(buffer, begin.e(), end.b(), new String[] { TemplateConstants.ARG_SEP }, false, TemplateConstants.SPEC,
+                    TemplateConstants.INHIBS_EXPRESSION);
+            expression = new TemplateCallExpression(buffer.substring(limits.b(), begin.b()), script);
+            expression.setPos(new Int2(limits.b(), begin.b()));
+            for (final Int2 pos : positions) {
+                expression.addArgument(TemplateExpression.fromString(buffer, pos, script));
+            }
+        } else {
+            expression = new TemplateCallExpression(buffer.substring(limits.b(), limits.e()), script);
+            expression.setPos(new Int2(limits.b(), limits.e()));
+        }
+        expression.setPos(limits);
+        if (filter != null) {
+            expression.setFilter(filter);
+        }
+        return expression;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateCallSetExpression.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateCallSetExpression.java
new file mode 100644
index 0000000..cd07950
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateCallSetExpression.java
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.Template;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateElement;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.eval.merge.MergeTools;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateFeatureStatement;
+import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateForStatement;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * This is a sequence of variable call expression (TemplateCallExpression).
+ * <p>
+ * For example, "a.b.c(d,e).f" is a sequence with four variables call
+ * expressions : "a", "b", "c(d,e)", and "f".
+ * 
+ * 
+ */
+public class TemplateCallSetExpression extends TemplateExpression {
+
+    /**
+     * Variables call expressions.
+     */
+    protected List calls = new ArrayList();
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public TemplateCallSetExpression(IScript script) {
+        super(script);
+    }
+
+    /**
+     * Adds a call expression.
+     * 
+     * @param call
+     *            is the new call
+     */
+    public void addCall(TemplateCallExpression call) {
+        if (calls.size() > 0) {
+            TemplateCallExpression last = (TemplateCallExpression) calls.get(calls.size() - 1);
+            last.setNextCall(call);
+        }
+        calls.add(call);
+        call.setParent(this);
+    }
+
+    /**
+     * Gets the first call of the set, or null is the set is empty.
+     * 
+     * @return the first call of the set, or null
+     */
+    public TemplateCallExpression getFirst() {
+        if (calls.size() > 0) {
+            return (TemplateCallExpression) calls.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets an iterator for the calls.
+     * 
+     * @return an iterator for the calls
+     */
+    public Iterator iterator() {
+        return calls.iterator();
+    }
+
+    /**
+     * Indicates if this set is a predefined link.
+     * <p>
+     * Samples:
+     * <li>i()</li>
+     * <li>args(?)</li>
+     * <li>startUserCode</li>
+     * <li>endUserCode</li>
+     * 
+     * @return true if this set is a predefined link
+     */
+    public boolean isPredefined() {
+        boolean predefined = false;
+        if (this.calls.size() > 0) {
+            TemplateCallExpression call = (TemplateCallExpression) calls.get(0);
+            if (call.link.equals(TemplateConstants.LINK_NAME_INDEX) && call.arguments.size() == 0 && "".equals(call.getPrefix())) {
+                return true;
+            } else if (call.link.equals(TemplateConstants.LINK_NAME_ARGS) && call.arguments.size() == 1 && "".equals(call.getPrefix())) {
+                predefined = true;
+            } else if (call.link.equals(TemplateConstants.USER_BEGIN_NAME) && call.arguments.size() == 0) {
+                if (parent instanceof TemplateFeatureStatement) {
+                    predefined = true;
+                }
+            } else if (call.link.equals(TemplateConstants.USER_END_NAME) && call.arguments.size() == 0) {
+                if (parent instanceof TemplateFeatureStatement) {
+                    predefined = true;
+                }
+            }
+        }
+        return predefined;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException {
+        script.contextPush(IScript.CURRENT_NODE, current);
+        try {
+            Iterator calls = this.calls.iterator();
+            if (calls.hasNext()) {
+                TemplateCallExpression call = (TemplateCallExpression) calls.next();
+                // Predefined links
+                boolean predefined = false;
+                if (call.link.equals(TemplateConstants.LINK_NAME_INDEX) && call.arguments.size() == 0 && "".equals(call.getPrefix())) {
+                    Integer index = (Integer) script.contextPeek(IScript.WHILE_INDEX);
+                    if (index == null) {
+                        index = new Integer(0);
+                    }
+                    current = new ENode(index.intValue(), current);
+                    predefined = true;
+                } else if (call.link.equals(TemplateConstants.LINK_NAME_ARGS) && call.arguments.size() == 1 && "".equals(call.getPrefix())) {
+                    ENode[] templateArgs = (ENode[]) script.contextPeek(IScript.TEMPLATE_ARGS);
+                    if (templateArgs == null) {
+                        templateArgs = new ENode[] {};
+                    }
+                    ENode index = ((TemplateExpression) call.arguments.get(0)).evaluate(current, script, mode);
+                    try {
+                        int i = index.getInt();
+                        if (i < templateArgs.length) {
+                            current = templateArgs[i];
+                            predefined = true;
+                        } else {
+                            throw new ENodeException(
+                                    AcceleoGenMessages.getString("TemplateCallSetExpression.UnresolvedArgument", new Object[] { Integer.toString(i), }), call.getPos(), script, current, true); //$NON-NLS-1$
+                        }
+                    } catch (ENodeCastException e) {
+                        throw new ENodeException(AcceleoGenMessages.getString("TemplateCallSetExpression.InvalidArgument"), call.getPos(), script, current, true); //$NON-NLS-1$
+                    }
+                } else if (call.link.equals(TemplateConstants.USER_BEGIN_NAME) && call.arguments.size() == 0) {
+                    current = new ENode(MergeTools.DEFAULT_USER_BEGIN, current);
+                    predefined = true;
+                } else if (call.link.equals(TemplateConstants.USER_END_NAME) && call.arguments.size() == 0) {
+                    current = new ENode(MergeTools.DEFAULT_USER_END, current);
+                    predefined = true;
+                }
+                if (predefined) {
+                    if (calls.hasNext()) {
+                        call = (TemplateCallExpression) calls.next();
+                    } else {
+                        return current;
+                    }
+                }
+                // Dynamic links
+                ENode first = call.evaluate(current, script, mode);
+                current = first;
+                while (calls.hasNext()) {
+                    call = (TemplateCallExpression) calls.next();
+                    current = call.evaluate(current, script, mode);
+                }
+                // Put linked object
+                if (!predefined) {
+                    if (current.isString() && first.isEObject() && !first.isContainment()) {
+                        try {
+                            ENode node = new ENode("", first); //$NON-NLS-1$
+                            if (node.getTextModelMapping() != null) {
+                                node.getTextModelMapping().linkBegin(first.getEObject());
+                            }
+                            node.append(current);
+                            if (node.getTextModelMapping() != null) {
+                                node.getTextModelMapping().linkEnd();
+                            }
+                            current = node;
+                        } catch (ENodeCastException e) {
+                            // Never catch
+                        }
+                    }
+                    if (first.isOptional()) {
+                        current.setOptional(true);
+                    }
+                }
+            }
+            return current;
+        } finally {
+            script.contextPop(IScript.CURRENT_NODE);
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        StringBuffer buffer = new StringBuffer(""); //$NON-NLS-1$
+        Iterator calls = this.calls.iterator();
+        while (calls.hasNext()) {
+            TemplateCallExpression call = (TemplateCallExpression) calls.next();
+            buffer.append(call.toString());
+            if (calls.hasNext()) {
+                buffer.append(TemplateConstants.CALL_SEP);
+            }
+        }
+        return buffer.toString();
+    }
+
+    /* (non-Javadoc) */
+    public static TemplateExpression fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        Int2 trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+        if (trim.b() == -1) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+        } else {
+            limits = trim;
+        }
+        Int2[] positions = TextSearch.getDefaultSearch().splitPositionsIn(buffer, limits.b(), limits.e(), new String[] { TemplateConstants.CALL_SEP }, false, TemplateConstants.SPEC,
+                TemplateConstants.INHIBS_EXPRESSION);
+        TemplateCallSetExpression expression = new TemplateCallSetExpression(script);
+        expression.setPos(limits);
+        for (Int2 pos : positions) {
+            expression.addCall((TemplateCallExpression) TemplateCallExpression.fromString(buffer, pos, script));
+        }
+        return expression;
+    }
+
+    /**
+     * Gets the root resolver for this link : EClassifier for the block
+     * container like "for" and "script".
+     * 
+     * @param defaultRoot
+     *            is the default container for the current template
+     * @param gen
+     *            is the script
+     * @return the root resolver for this link
+     */
+    public Object getRootResolver(Object defaultRoot, IScript gen) {
+        TemplateElement parent = getParent();
+        TemplateElement current = this;
+        boolean inForBlock = false;
+        while (parent != null) {
+            if (parent instanceof Template && parent.getParent() instanceof TemplateForStatement) {
+                inForBlock = true;
+            } else if (parent instanceof TemplateForStatement) {
+                if (inForBlock) {
+                    TemplateExpression forCondition = ((TemplateForStatement) parent).getCondition();
+                    List testElements = forCondition.getAllElements(TemplateCallSetExpression.class);
+                    if (testElements.size() > 0) {
+                        TemplateCallSetExpression firstCallSet = (TemplateCallSetExpression) testElements.get(0);
+                        if (firstCallSet != null) {
+                            Object resolvedType = firstCallSet.getRootResolver(defaultRoot, gen);
+                            Iterator calls = firstCallSet.iterator();
+                            while (resolvedType != null && calls.hasNext()) {
+                                TemplateCallExpression call = (TemplateCallExpression) calls.next();
+                                resolvedType = gen.resolveType(resolvedType, call, 0);
+                            }
+                            return resolvedType;
+                        }
+                    }
+                }
+            } else if (parent instanceof TemplateCallExpression && ((TemplateCallExpression) parent).filter == current && parent.getParent() instanceof TemplateCallSetExpression) {
+                TemplateCallSetExpression callSet = (TemplateCallSetExpression) parent.getParent();
+                Object resolvedType = callSet.getRootResolver(defaultRoot, gen);
+                Iterator calls = callSet.iterator();
+                while (resolvedType != null && calls.hasNext()) {
+                    TemplateCallExpression call = (TemplateCallExpression) calls.next();
+                    resolvedType = gen.resolveType(resolvedType, call, 0);
+                    if (call == parent) {
+                        break;
+                    }
+                }
+                return resolvedType;
+            }
+            current = parent;
+            parent = parent.getParent();
+        }
+        return defaultRoot;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateExpression.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateExpression.java
new file mode 100644
index 0000000..c430707
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateExpression.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateElement;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * Expressions are defined recursively, as is usual for programming language
+ * specifications. Each expression is included in a statement.
+ * 
+ * 
+ */
+public abstract class TemplateExpression extends TemplateElement {
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public TemplateExpression(IScript script) {
+        super(script);
+    }
+
+    /**
+     * Evaluates this template expression on an ENode. The result node of
+     * generation is also an ENode. Expressions are defined recursively, so the
+     * result is transmitted from an expression to another.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param script
+     *            is the generator's configuration
+     * @param mode
+     *            is the mode in which to launch, one of the mode constants
+     *            defined - RUN_MODE or DEBUG_MODE
+     * @return the result node of generation
+     * @throws ENodeException
+     * @throws FactoryException
+     * @see ENode
+     */
+    public abstract ENode evaluate(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException;
+
+    /**
+     * It checks the syntax and creates an expression for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param buffer
+     *            is the textual representation of the templates
+     * @param limits
+     *            delimits the part of the text to be parsed for this expression
+     * @param script
+     *            is the generator's configuration
+     * @return the new expression
+     * @throws TemplateSyntaxException
+     */
+    public static TemplateExpression fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        Int2 trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+        if (trim.b() == -1) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+        } else {
+            limits = trim;
+        }
+        TemplateExpression expression = TemplateOperatorExpression.fromString(buffer, limits, script);
+        if (expression != null) {
+            return expression;
+        }
+        expression = TemplateNotExpression.fromString(buffer, limits, script);
+        if (expression != null) {
+            return expression;
+        }
+        expression = TemplateParenthesisExpression.fromString(buffer, limits, script);
+        if (expression != null) {
+            return expression;
+        }
+        expression = TemplateLiteralExpression.fromString(buffer, limits, script);
+        if (expression != null) {
+            return expression;
+        }
+        expression = TemplateCallSetExpression.fromString(buffer, limits, script);
+        return expression;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateLiteralExpression.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateLiteralExpression.java
new file mode 100644
index 0000000..87e1317
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateLiteralExpression.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EcorePackage;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.tools.format.Conventions;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * The simplest expression is a literal expression. Literal expressions are also
+ * known as self-evaluating data, because the value of a literal expression is
+ * the corresponding datum. Strings <b>"</b>...<b>"</b>, numbers
+ * <b>0</b>..<b>*</b>, <b>null</b>, and booleans <b>true</b> or <b>false</b> are
+ * all valid literal expressions. However, for strings, the first and the last
+ * '"' are ignored to create the real value.
+ * 
+ * 
+ */
+public class TemplateLiteralExpression extends TemplateExpression {
+
+    /**
+     * Boolean literal : true.
+     */
+    protected static final String LITERAL_TRUE = "true"; //$NON-NLS-1$
+
+    /**
+     * Boolean literal : false.
+     */
+    protected static final String LITERAL_FALSE = "false"; //$NON-NLS-1$
+
+    /**
+     * Langage literal : null.
+     */
+    protected static final String LITERAL_NULL = "null"; //$NON-NLS-1$
+
+    /**
+     * The value of the litteral expression. It's a String, a Boolean, an
+     * Integer, or null.
+     */
+    protected Object value;
+
+    /**
+     * Constructor.
+     * 
+     * @param value
+     *            is the string value of the expression
+     * @param script
+     *            is the script
+     */
+    public TemplateLiteralExpression(String value, IScript script) {
+        super(script);
+        this.value = value;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param value
+     *            is the boolean value of the expression
+     * @param script
+     *            is the script
+     */
+    public TemplateLiteralExpression(boolean value, IScript script) {
+        super(script);
+        this.value = new Boolean(value);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param value
+     *            is the numeric value of the expression
+     * @param script
+     *            is the script
+     */
+    public TemplateLiteralExpression(int value, IScript script) {
+        super(script);
+        this.value = new Integer(value);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param value
+     *            is the double value of the expression
+     * @param script
+     *            is the script
+     */
+    public TemplateLiteralExpression(double value, IScript script) {
+        super(script);
+        this.value = new Double(value);
+    }
+
+    /**
+     * Constructor. The value is null.
+     * 
+     * @param script
+     *            is the script
+     */
+    public TemplateLiteralExpression(IScript script) {
+        super(script);
+        this.value = null;
+    }
+
+    /**
+     * @return the value
+     */
+    public Object getValue() {
+        return value;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException {
+        ENode result;
+        if (value == null) {
+            result = new ENode(ENode.EMPTY, current);
+        } else if (value instanceof String) {
+            result = new ENode((String) value, current);
+        } else if (value instanceof Boolean) {
+            result = new ENode(((Boolean) value).booleanValue(), current);
+        } else if (value instanceof Integer) {
+            result = new ENode(((Integer) value).intValue(), current);
+        } else if (value instanceof Double) {
+            result = new ENode(((Double) value).doubleValue(), current);
+        } else {
+            result = new ENode(ENode.EMPTY, current);
+        }
+        return result;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        if (value == null) {
+            return TemplateLiteralExpression.LITERAL_NULL;
+        } else if (value instanceof String) {
+            return TemplateConstants.LITERAL[0] + Conventions.formatString((String) value) + TemplateConstants.LITERAL[1];
+        } else {
+            return value.toString();
+        }
+    }
+
+    /**
+     * Resolves this literal as an EClassifier link.
+     * 
+     * @return an EClassifier or null if not found
+     */
+    public EClassifier resolveAsEClassifier() {
+        if (value != null && value instanceof String && script != null && script instanceof SpecificScript && ((SpecificScript) script).getMetamodel() != null) {
+            String id = (String) value;
+            EClassifier result = ETools.getEClassifier(((SpecificScript) script).getMetamodel(), id);
+            if (result == null) {
+                result = ETools.getEClassifier(EcorePackage.eINSTANCE, id);
+            }
+            return result;
+        } else {
+            return null;
+        }
+    }
+
+    /* (non-Javadoc) */
+    public static TemplateExpression fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        Int2 trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+        if (trim.b() == -1) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+        } else {
+            limits = trim;
+        }
+        TemplateExpression expression;
+        String text = buffer.substring(limits.b(), limits.e());
+        if (text.length() >= TemplateConstants.LITERAL[0].length() + TemplateConstants.LITERAL[1].length() && text.startsWith(TemplateConstants.LITERAL[0])) {
+            if (!text.endsWith(TemplateConstants.LITERAL[1])) {
+                throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidLitteral"), script, limits); //$NON-NLS-1$
+            }
+            String value = text.substring(TemplateConstants.LITERAL[0].length(), text.length() - TemplateConstants.LITERAL[1].length());
+            expression = new TemplateLiteralExpression(Conventions.unformatString(value), script);
+        } else {
+            if (text.equals(TemplateLiteralExpression.LITERAL_TRUE)) {
+                expression = new TemplateLiteralExpression(true, script);
+            } else if (text.equals(TemplateLiteralExpression.LITERAL_FALSE)) {
+                expression = new TemplateLiteralExpression(false, script);
+            } else if (text.equals(TemplateLiteralExpression.LITERAL_NULL)) {
+                expression = new TemplateLiteralExpression(script);
+                /*
+                 * If first char is a digit, then it might be an integer or
+                 * double.
+                 */
+            } else if (text.length() > 0 && (text.charAt(0) == '-' || Character.isDigit(text.charAt(0)))) {
+                if (text.indexOf(".") > -1) { //$NON-NLS-1$
+                    try {
+                        double value = Double.parseDouble(text);
+                        expression = new TemplateLiteralExpression(value, script);
+                    } catch (NumberFormatException e) {
+                        expression = null;
+                    }
+                } else {
+                    try {
+                        int value = Integer.parseInt(text);
+                        expression = new TemplateLiteralExpression(value, script);
+                    } catch (NumberFormatException e) {
+                        expression = null;
+                    }
+                }
+            } else {
+                expression = null;
+            }
+        }
+        if (expression != null) {
+            expression.setPos(limits);
+        }
+        return expression;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateNotExpression.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateNotExpression.java
new file mode 100644
index 0000000..b141ba3
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateNotExpression.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * This operator is used to create negative expressions.
+ * <p>
+ * The general syntax is : ! expression
+ * 
+ * 
+ */
+public class TemplateNotExpression extends TemplateExpression {
+
+    /**
+     * The expression after the not operator.
+     */
+    protected TemplateExpression expression;
+
+    /**
+     * Constructor.
+     * 
+     * @param expression
+     *            is the expression after the not operator
+     * @param script
+     *            is the script
+     */
+    public TemplateNotExpression(TemplateExpression expression, IScript script) {
+        super(script);
+        this.expression = expression;
+        this.expression.setParent(this);
+    }
+
+    /**
+     * @return the expression
+     */
+    public TemplateExpression getExpression() {
+        return expression;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException {
+        final ENode test = expression.evaluate(current, script, mode);
+        ENode result;
+        try {
+            boolean value = test.getBoolean();
+            result = new ENode(!value, current);
+        } catch (final ENodeCastException e1) {
+            try {
+                final Object boolValue = test.getAdapterValue(boolean.class);
+                if (boolValue instanceof Boolean) {
+                    result = new ENode(!((Boolean) boolValue).booleanValue(), current);
+                } else {
+                    throw new ENodeException(AcceleoGenMessages.getString("ENodeError.BooleanRequired", new Object[] { test.getType(), }), expression.getPos(), script, current, true); //$NON-NLS-1$
+                }
+            } catch (final ENodeCastException e2) {
+                throw new ENodeException(e2.getMessage(), expression.getPos(), script, current, true);
+            }
+        }
+        return result;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return TemplateConstants.NOT + expression.toString();
+    }
+
+    /* (non-Javadoc) */
+    public static TemplateExpression fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        final Int2 trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+        if (trim.b() == -1) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+        } else {
+            limits = trim;
+        }
+        final String text = buffer.substring(limits.b(), limits.e());
+        if (text.startsWith(TemplateConstants.NOT)) {
+            final TemplateExpression expression = TemplateExpression.fromString(buffer, new Int2(limits.b() + TemplateConstants.NOT.length(), limits.e()), script);
+            final TemplateNotExpression notExpression = new TemplateNotExpression(expression, script);
+            notExpression.setPos(limits);
+            return notExpression;
+        } else {
+            return null;
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateOperatorExpression.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateOperatorExpression.java
new file mode 100644
index 0000000..d75a0e9
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateOperatorExpression.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * Operators combine sub-expressions (operands) to create more complex
+ * expressions.
+ * <p>
+ * The general syntax for using operators is :
+ * <li>TemplateExpression (Operator TemplateExpression)+</li>
+ * <p>
+ * <p>
+ * This generator has 3 types of operators:
+ * <li>Arithmetic operators : + , - , / , *</li>
+ * <li>Boolean operators : || , &&</li>
+ * <li>Comparison operators : == , !=, > , >= , < , <=</li>
+ * 
+ * 
+ */
+public class TemplateOperatorExpression extends TemplateExpression {
+
+    /**
+     * Operator name.
+     */
+    protected String operator;
+
+    /**
+     * Operands in order.
+     */
+    protected List children = new ArrayList();
+
+    /**
+     * Constructor.
+     * 
+     * @param operator
+     *            is the operator name
+     * @param script
+     *            is the script
+     */
+    public TemplateOperatorExpression(String operator, IScript script) {
+        super(script);
+        this.operator = operator;
+    }
+
+    /**
+     * @return the operator
+     */
+    public String getOperator() {
+        return operator;
+    }
+
+    /**
+     * Adds an operand.
+     * 
+     * @param expression
+     *            is the new operand
+     */
+    public void addChild(TemplateExpression expression) {
+        children.add(expression);
+        expression.setParent(this);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException {
+        try {
+            final Iterator children = this.children.iterator();
+            ENode last = null;
+            while (children.hasNext()) {
+                final TemplateExpression child = (TemplateExpression) children.next();
+                ENode node = child.evaluate(current, script, mode);
+                if (last == null || last.isBoolean()) {
+                    if (operator.equals(TemplateConstants.OPERATOR_OR)) {
+                        if (node.isBoolean() && node.getBoolean()) {
+                            last = node;
+                            break;
+                        }
+                    } else if (operator.equals(TemplateConstants.OPERATOR_AND)) {
+                        if (node.isBoolean() && !node.getBoolean()) {
+                            last = node;
+                            break;
+                        }
+                    }
+                }
+                if (last != null) {
+                    if (operator.equals(TemplateConstants.OPERATOR_OR)) {
+                        node = ExpressionTools.or(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_AND)) {
+                        node = ExpressionTools.and(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_EQUALS)) {
+                        node = ExpressionTools.equals(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_NOT_EQUALS)) {
+                        node = ExpressionTools.notEquals(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_SUP_EQUALS)) {
+                        node = ExpressionTools.supE(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_INF_EQUALS)) {
+                        node = ExpressionTools.infE(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_SUP)) {
+                        node = ExpressionTools.sup(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_INF)) {
+                        node = ExpressionTools.inf(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_ADD)) {
+                        node = ExpressionTools.add(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_SUB)) {
+                        node = ExpressionTools.sub(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_DIV)) {
+                        node = ExpressionTools.div(last, node);
+                    } else if (operator.equals(TemplateConstants.OPERATOR_MUL)) {
+                        node = ExpressionTools.mul(last, node);
+                    }
+                }
+                last = node;
+            }
+            ENode result;
+            if (last != null) {
+                result = last;
+            } else {
+                result = new ENode(ENode.EMPTY, current);
+            }
+            return result;
+        } catch (final ENodeCastException e) {
+            throw new ENodeException(e.getMessage(), pos, script, current, true);
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        final StringBuffer buffer = new StringBuffer(""); //$NON-NLS-1$
+        final Iterator children = this.children.iterator();
+        while (children.hasNext()) {
+            final TemplateExpression child = (TemplateExpression) children.next();
+            buffer.append(child.toString());
+            if (children.hasNext()) {
+                buffer.append(' ' + operator + ' ');
+            }
+        }
+        return buffer.toString();
+    }
+
+    /* (non-Javadoc) */
+    public static TemplateExpression fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        final Int2 trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+        if (trim.b() == -1) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+        } else {
+            limits = trim;
+        }
+        for (String element : TemplateConstants.OPERATORS) {
+            final Int2[] positions = TextSearch.getDefaultSearch().splitPositionsIn(buffer, limits.b(), limits.e(), new String[] { element }, false, TemplateConstants.SPEC,
+                    TemplateConstants.INHIBS_EXPRESSION);
+            if (positions.length > 1) {
+                final TemplateOperatorExpression expression = new TemplateOperatorExpression(element, script);
+                expression.setPos(limits);
+                for (final Int2 pos : positions) {
+                    expression.addChild(TemplateExpression.fromString(buffer, pos, script));
+                }
+                return expression;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateParenthesisExpression.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateParenthesisExpression.java
new file mode 100644
index 0000000..1376342
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/expressions/TemplateParenthesisExpression.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.expressions;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * The valuation of a parenthesis expression is the valuation of the expression
+ * inside the parenthesis. The type of a parenthesis expression is the same as
+ * the type of the expression inside the parenthesis.
+ * 
+ * 
+ */
+public class TemplateParenthesisExpression extends TemplateExpression {
+
+    /**
+     * The expression inside the parenthesis.
+     */
+    protected TemplateExpression expression;
+
+    /**
+     * Constructor.
+     * 
+     * @param expression
+     *            is the expression inside the parenthesis
+     * @param script
+     *            is the script
+     */
+    public TemplateParenthesisExpression(TemplateExpression expression, IScript script) {
+        super(script);
+        this.expression = expression;
+        this.expression.setParent(this);
+    }
+
+    /**
+     * @return the expression
+     */
+    public TemplateExpression getExpression() {
+        return expression;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(ENode current, IScript script, LaunchManager mode) throws ENodeException, FactoryException {
+        ENode result = expression.evaluate(current, script, mode);
+        return result;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return TemplateConstants.PARENTH[0] + expression.toString() + TemplateConstants.PARENTH[1];
+    }
+
+    /* (non-Javadoc) */
+    public static TemplateExpression fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        Int2 trim = TextSearch.getDefaultSearch().trim(buffer, limits.b(), limits.e());
+        if (trim.b() == -1) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingElement"), script, limits); //$NON-NLS-1$
+        } else {
+            limits = trim;
+        }
+        Int2 begin = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.PARENTH[0], limits.b(), limits.e());
+        if (begin.b() == limits.b()) {
+            Int2 end = TextSearch.getDefaultSearch().blockIndexEndIn(buffer, TemplateConstants.PARENTH[0], TemplateConstants.PARENTH[1], begin.b(), limits.e(), true, TemplateConstants.SPEC,
+                    TemplateConstants.INHIBS_EXPRESSION);
+            if (end.e() == limits.e()) {
+                TemplateExpression expression = TemplateExpression.fromString(buffer, new Int2(limits.b() + TemplateConstants.PARENTH[0].length(), limits.e() - TemplateConstants.PARENTH[1].length()),
+                        script);
+                TemplateParenthesisExpression parenthesis = new TemplateParenthesisExpression(expression, script);
+                parenthesis.setPos(limits);
+                return parenthesis;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/AbstractScript.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/AbstractScript.java
new file mode 100644
index 0000000..531b3a6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/AbstractScript.java
@@ -0,0 +1,498 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeSet;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalJavaService;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalModel;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.SystemServicesFactory;
+
+/**
+ * Abstract generator configuration.
+ * 
+ * 
+ */
+public abstract class AbstractScript implements IScript {
+
+    /**
+     * The identifier of the internal extension point specifying the
+     * implementation to use with an acceleo script loader.
+     */
+    public static final String SCRIPT_LOADER_EXTENSION_ID = "org.eclipse.sirius.query.legacy.gen.scriptloader"; //$NON-NLS-1$
+
+    /* (non-Javadoc) */
+    public ENode eGet(TemplateCallExpression call, ENode node, ENode[] args, LaunchManager mode, boolean recursiveSearch) throws FactoryException, ENodeException {
+        // Services to apply on an ENode or an ENodeList
+        Iterator imports = this.imports.iterator();
+        while (imports.hasNext()) {
+            final IEvalSettings anImport = (IEvalSettings) imports.next();
+            if (anImport instanceof EvalJavaService) {
+                if ((recursiveSearch || !((EvalJavaService) anImport).hasScriptContext()) && anImport.validateCall(call)) {
+                    ((EvalJavaService) anImport).setMode(EvalJavaService.MODE_ENODE);
+                    ENode sub = anImport.eGet(call, node, args, mode, false);
+                    if (sub != null) {
+                        return sub;
+                    }
+                    ((EvalJavaService) anImport).setMode(EvalJavaService.MODE_LIST);
+                    sub = anImport.eGet(call, node, args, mode, false);
+                    if (sub != null) {
+                        return sub;
+                    }
+                }
+            }
+        }
+        // Templates to apply on an EObject or an ENodeList
+        ENode eval;
+        if (validateCall(call)) {
+            if (node.isEObject()) {
+                eval = eGetTemplate(node, call.getLink(), args, mode);
+            } else if (node.isList()) {
+                // Iterate on the list
+                boolean found = false;
+                final ENodeList res = new ENodeList();
+                try {
+                    if (node.getList().size() == 0 && recursiveSearch /*
+                                                                       * ENode
+                                                                       * services
+                                                                       * OK
+                                                                       */) {
+                        found = true;
+                    }
+                    final ENodeIterator it = node.getList().iterator();
+                    while (it.hasNext()) {
+                        final ENode child = eGet(call, it.next(), args, mode, recursiveSearch);
+                        if (child != null) {
+                            found = true;
+                            res.add(child);
+                        }
+                    }
+                } catch (final ENodeCastException e) {
+                    // Never catch
+                }
+                if (found) {
+                    eval = new ENode(res, node);
+                } else {
+                    eval = null;
+                }
+            } else {
+                eval = null;
+            }
+        } else {
+            eval = null;
+        }
+        if (eval == null) {
+            if (recursiveSearch) {
+                // Other imports
+                imports = this.imports.iterator();
+                while (imports.hasNext()) {
+                    final IEvalSettings anImport = (IEvalSettings) imports.next();
+                    if (anImport.validateCall(call)) {
+                        if (anImport instanceof SpecificScript) {
+                            final ENode sub = ((SpecificScript) anImport).eGetTemplate(node, call.getLink(), args, mode);
+                            if (sub != null) {
+                                return sub;
+                            }
+                        } else if (anImport instanceof EvalJavaService) {
+                            ((EvalJavaService) anImport).setMode(EvalJavaService.MODE_DEFAULT);
+                            final ENode sub = anImport.eGet(call, node, args, mode, false);
+                            if (sub != null) {
+                                return sub;
+                            }
+                        } else if (anImport instanceof EvalModel
+                                && (TemplateConstants.LINK_PREFIX_METAMODEL.equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_METAMODEL_SHORT.equals(call.getPrefix()))) {
+                            if (node.isEObject()) {
+                                final ENode sub = anImport.eGet(call, node, args, mode, false);
+                                if (sub != null) {
+                                    return sub;
+                                }
+                            } else if (node.isList()) {
+                                // Iterate on the list
+                                boolean found = false;
+                                final ENodeList res = new ENodeList();
+                                try {
+                                    if (node.getList().size() == 0 && recursiveSearch) {
+                                        found = true;
+                                    }
+                                    final ENodeIterator it = node.getList().iterator();
+                                    while (it.hasNext()) {
+                                        final ENode next = it.next();
+                                        final ENode child = anImport.eGet(call, next, args, mode, false);
+                                        if (child != null) {
+                                            found = true;
+                                            res.add(child);
+                                        }
+                                    }
+                                } catch (final ENodeCastException e) {
+                                    // Never catch
+                                }
+                                if (found) {
+                                    return new ENode(res, node);
+                                }
+                            } else {
+                                final ENode sub = anImport.eGet(call, node, args, mode, false);
+                                if (sub != null) {
+                                    return sub;
+                                }
+                            }
+                        } else {
+                            final ENode sub = anImport.eGet(call, node, args, mode, false);
+                            if (sub != null) {
+                                return sub;
+                            }
+                        }
+                    }
+                }
+            } else {
+                // Other imports
+                imports = this.imports.iterator();
+                while (imports.hasNext()) {
+                    final IEvalSettings anImport = (IEvalSettings) imports.next();
+                    if (anImport instanceof AbstractScript && !(anImport instanceof SpecificScript) && !(anImport instanceof EmptyScript) && anImport.validateCall(call)) {
+                        final ENode sub = anImport.eGet(call, node, args, mode, false);
+                        if (sub != null) {
+                            return sub;
+                        }
+                    } else if (anImport instanceof EvalJavaService && !((EvalJavaService) anImport).hasScriptContext() && anImport.validateCall(call)) {
+                        ((EvalJavaService) anImport).setMode(EvalJavaService.MODE_DEFAULT);
+                        final ENode sub = anImport.eGet(call, node, args, mode, false);
+                        if (sub != null) {
+                            return sub;
+                        }
+                    }
+                }
+            }
+        }
+        if (eval == null && node.isNull()) {
+            return node;
+        } else {
+            return eval;
+        }
+    }
+
+    /**
+     * Computes a child node of generation for a node and a template name. The
+     * template is evaluated on an EObject, so the given node must be an
+     * EObject.
+     * 
+     * @param node
+     *            is the parent node of generation
+     * @param name
+     *            is the template name
+     * @param args
+     *            is the list of arguments
+     * @param mode
+     *            is the mode in which to launch, one of the mode constants
+     *            defined - RUN_MODE or DEBUG_MODE
+     * @return the child node of generation, or null if the template doesn't
+     *         exist, or null if the type of the node isn't valid
+     * @throws ENodeException
+     * @throws FactoryException
+     */
+    public abstract ENode eGetTemplate(ENode node, String name, ENode[] args, LaunchManager mode) throws ENodeException, FactoryException;
+
+    /* (non-Javadoc) */
+    public void addImport(IEvalSettings element) {
+        if (element != null) {
+            this.imports.add(element);
+        }
+    }
+
+    /* (non-Javadoc) */
+    public void removeImport(IEvalSettings element) {
+        if (element != null) {
+            this.imports.remove(element);
+        }
+    }
+
+    /* (non-Javadoc) */
+    public void clearImports() {
+        imports.clear();
+    }
+
+    /**
+     * All the elements that are used after this one during generation.
+     */
+    protected Set imports = new TreeSet(new Comparator() {
+        public int compare(Object arg0, Object arg1) {
+            // Remark : Low priority for EvalModel
+            if (!(arg0 instanceof EvalModel) && arg1 instanceof EvalModel) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }
+    });
+
+    /**
+     * @return the imports
+     */
+    public Set getImports() {
+        return imports;
+    }
+
+    /**
+     * Returns the factory that produces the system services for this script.
+     * 
+     * @return the factory that produces the system services for this script
+     */
+    protected SystemServicesFactory getSystemServicesFactory() {
+        if (systemServicesFactory == null) {
+            systemServicesFactory = createSystemServicesFactory();
+        }
+        return systemServicesFactory;
+    }
+
+    private SystemServicesFactory systemServicesFactory = null;
+
+    /**
+     * Creates the factory that produces the system services for this script.
+     * 
+     * @return the new factory
+     */
+    protected SystemServicesFactory createSystemServicesFactory() {
+        return new SystemServicesFactory();
+    }
+
+    /* (non-Javadoc) */
+    public IScript[] goToSpecifics() {
+        if (goToSpecifics == null) {
+            if (AbstractScript.getScriptLoader() != null) {
+                goToSpecifics = AbstractScript.getScriptLoader().goToSpecifics(this);
+            }
+        }
+        return goToSpecifics;
+    }
+
+    private IScript[] goToSpecifics = null;
+
+    /* (non-Javadoc) */
+    public IScript getSpecific() {
+        return specific;
+    }
+
+    /* (non-Javadoc) */
+    public void setSpecific(IScript specific) {
+        this.specific = specific;
+        this.goToSpecifics = null;
+    }
+
+    /**
+     * The more specific script. The specific script is used before this one to
+     * resolve the links.
+     */
+    protected IScript specific = null;
+
+    /* (non-Javadoc) */
+    public File getFile() {
+        return null;
+    }
+
+    /* (non-Javadoc) */
+    public Object contextPeek(Object key) {
+        final Stack stack = (Stack) context.get(key);
+        if (stack != null && !stack.isEmpty()) {
+            final Object result = stack.peek();
+            if (result instanceof ENode) {
+                return ((ENode) result).copy();
+            } else if (result instanceof ENode[]) {
+                final ENode[] copy = new ENode[((ENode[]) result).length];
+                for (int i = 0; i < copy.length; i++) {
+                    copy[i] = ((ENode[]) result)[i].copy();
+                }
+                return copy;
+            } else {
+                return result;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /* (non-Javadoc) */
+    public Object contextAt(Object key, int index) {
+        final Stack stack = (Stack) context.get(key);
+        if (stack != null) {
+            if (index >= 0 && index < stack.size()) {
+                final Object result = stack.elementAt(stack.size() - index - 1);
+                if (result instanceof ENode) {
+                    return ((ENode) result).copy();
+                } else if (result instanceof ENode[]) {
+                    final ENode[] copy = new ENode[((ENode[]) result).length];
+                    for (int i = 0; i < copy.length; i++) {
+                        copy[i] = ((ENode[]) result)[i].copy();
+                    }
+                    return copy;
+                } else {
+                    return result;
+                }
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /* (non-Javadoc) */
+    public void contextPush(Object key, Object value) {
+        Stack stack = (Stack) context.get(key);
+        if (stack == null) {
+            stack = new Stack();
+            context.put(key, stack);
+        }
+        stack.push(value);
+    }
+
+    /* (non-Javadoc) */
+    public void contextPop(Object key) {
+        final Stack stack = (Stack) context.get(key);
+        if (stack != null) {
+            stack.pop();
+        }
+    }
+
+    /**
+     * Context that is used during generation.
+     */
+    private final Map context = new HashMap();
+
+    /**
+     * Resolves the type of the next step for the type of the previous node, and
+     * the new link.
+     * 
+     * @param type
+     *            is the type of the previous node
+     * @param call
+     *            is the new link
+     * @return the type of the next step
+     */
+    public Object resolveType(Object type, TemplateCallExpression call) {
+        return resolveType(type, call, 0);
+    }
+
+    /* (non-Javadoc) */
+    public Object resolveType(Object type, TemplateCallExpression call, int depth) {
+        if (depth < 1) {
+            final Iterator imports = this.imports.iterator();
+            while (imports.hasNext()) {
+                final IEvalSettings anImport = (IEvalSettings) imports.next();
+                if (anImport.validateCall(call)) {
+                    final Object resolvedType = anImport.resolveType(type, call, 1);
+                    if (resolvedType != null) {
+                        return resolvedType;
+                    }
+                }
+            }
+        }
+        if (call.getLink().equals(TemplateConstants.LINK_NAME_INDEX) && call.getFirstArgument() == null && "".equals(call.getPrefix())) {
+            return IEvalSettings.GENERIC_TYPE;
+        } else if (call.getLink().equals(TemplateConstants.LINK_NAME_ARGS) && call.getArguments() != null && call.getArguments().size() == 1 && "".equals(call.getPrefix())) {
+            return IEvalSettings.GENERIC_TYPE;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the proposals of the next step for the type of the previous node.
+     * 
+     * @param type
+     *            is the type of the previous node
+     * @return the proposals of the next step
+     */
+    public Object[] getCompletionProposals(Object type) {
+        return getCompletionProposals(type, 0);
+    }
+
+    /* (non-Javadoc) */
+    public Object[] getCompletionProposals(Object type, int depth) {
+        final List result = new ArrayList();
+        if (depth < 1) {
+            final TreeSet orderedImports = new TreeSet(new Comparator() {
+                public int compare(Object arg0, Object arg1) {
+                    // Remark : High priority for EvalModel
+                    if (arg0 instanceof EvalModel && !(arg1 instanceof EvalModel)) {
+                        return -1;
+                    } else {
+                        return 1;
+                    }
+                }
+            });
+            orderedImports.addAll(this.imports);
+            final Iterator imports = orderedImports.iterator();
+            while (imports.hasNext()) {
+                final IEvalSettings anImport = (IEvalSettings) imports.next();
+                result.addAll(Arrays.asList(anImport.getCompletionProposals(type, 1)));
+            }
+        }
+        return result.toArray();
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        final StringBuffer text = new StringBuffer(""); //$NON-NLS-1$
+        text.append(TemplateConstants.IMPORT_BEGIN);
+        text.append('\n');
+        final Iterator imports = this.imports.iterator();
+        while (imports.hasNext()) {
+            final IEvalSettings anImport = (IEvalSettings) imports.next();
+            // Remark : toString -> Keep EvalModel only
+            if (anImport instanceof EvalModel) {
+                final String importValue = ((EvalModel) anImport).getUri();
+                if (importValue.length() > 0) {
+                    text.append(TemplateConstants.MODELTYPE_WORD);
+                    text.append(' ');
+                    text.append(importValue);
+                    text.append('\n');
+                }
+            }
+        }
+        text.append(TemplateConstants.IMPORT_END);
+        text.append("\n\n"); //$NON-NLS-1$
+        return text.toString();
+    }
+
+    /**
+     * @return the script loader that converts the script's content before
+     *         loading
+     */
+    protected static IScriptLoader getScriptLoader() {
+        if (AbstractScript.scriptLoader == null) {
+            return new DefaultScriptLoader();
+        }
+        return AbstractScript.scriptLoader;
+    }
+
+    private static IScriptLoader scriptLoader = null;
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/DefaultScriptLoader.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/DefaultScriptLoader.java
new file mode 100644
index 0000000..9c23120
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/DefaultScriptLoader.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A script loader that converts the script's content before loading. The
+ * default implementation returns the initial content.
+ * 
+ * 
+ */
+public class DefaultScriptLoader implements IScriptLoader {
+
+    /* (non-Javadoc) */
+    public String load(String content) {
+        return content;
+    }
+
+    /* (non-Javadoc) */
+    public IScript[] goToSpecifics(IScript script) {
+        List specifics = new ArrayList();
+        IScript specific = script.getSpecific();
+        while (specific != null) {
+            if (specific instanceof SpecificScript) {
+                specifics.add(0, specific);
+            }
+            specific = specific.getSpecific();
+        }
+        return (IScript[]) specifics.toArray(new IScript[specifics.size()]);
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/EmptyScript.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/EmptyScript.java
new file mode 100644
index 0000000..ca067ce
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/EmptyScript.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.Template;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxExceptions;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * Empty Generator configuration. <li>isDefault() == false</li> <li>isSpecific()
+ * == false</li> <li>hasFileTemplate() == false</li> <li>isGenerated(EObject) ==
+ * false</li> <li>hasError(EObject) == false</li>
+ * 
+ * 
+ */
+public class EmptyScript extends AbstractScript {
+
+    /**
+     * Constructor.
+     */
+    public EmptyScript() {
+        super();
+    }
+
+    /* (non-Javadoc) */
+    public boolean isDefault() {
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    public boolean isSpecific() {
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    public void reset() throws TemplateSyntaxExceptions {
+    }
+
+    /* (non-Javadoc) */
+    public boolean hasFileTemplate() {
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    public boolean isGenerated(EObject object) {
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    public IPath getFilePath(EObject object, boolean recursive) throws FactoryException {
+        return null;
+    }
+
+    /* (non-Javadoc) */
+    public boolean hasError(EObject object) {
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    public Template getTextTemplateForEObject(EObject object, String key) throws FactoryException, ENodeException {
+        throw new ENodeException(AcceleoGenMessages.getString("ENodeError.UnresolvedTemplate", new Object[] { key, }), new Int2(0, 0), this, object, false); //$NON-NLS-1$
+    }
+
+    /* (non-Javadoc) */
+    public Template getRootTemplate(EObject object, boolean recursive) throws FactoryException, ENodeException {
+        throw new ENodeException(AcceleoGenMessages.getString("ENodeError.UnresolvedRoot"), new Int2(0, 0), this, object, false); //$NON-NLS-1$
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode eGetTemplate(ENode node, String name, ENode[] args, LaunchManager mode) throws ENodeException, FactoryException {
+        return null;
+    }
+
+    /* (non-Javadoc) */
+    public boolean validateCall(TemplateCallExpression call) {
+        return false;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IEvalSettings.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IEvalSettings.java
new file mode 100644
index 0000000..e26aa1a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IEvalSettings.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
+
+/**
+ * An element that can be used during a code generation.
+ * 
+ * 
+ */
+public interface IEvalSettings {
+
+    /**
+     * Computes a child node of generation for a node and a link.
+     * 
+     * @param call
+     *            is the link
+     * @param node
+     *            is the parent node of generation
+     * @param args
+     *            is the list of arguments
+     * @param mode
+     *            is the mode in which to launch, one of the mode constants
+     *            defined - RUN_MODE or DEBUG_MODE
+     * @param recursiveSearch
+     *            to search in its imports
+     * @return the child node of generation
+     * @throws FactoryException
+     * @throws ENodeException
+     * @see ENode
+     */
+    public ENode eGet(TemplateCallExpression call, ENode node, ENode[] args, LaunchManager mode, boolean recursiveSearch) throws FactoryException, ENodeException;
+
+    /**
+     * Resolves the type of the next step for the type of the previous node, and
+     * the new link.
+     * 
+     * @param type
+     *            is the type of the previous node
+     * @param call
+     *            is the new link
+     * @param depth
+     *            is the depth of the script
+     * @return the type of the next step
+     */
+    public Object resolveType(Object type, TemplateCallExpression call, int depth);
+
+    /**
+     * The pass key. The type that is returned by services and template calls.
+     */
+    public static final Object GENERIC_TYPE = new Object();
+
+    /**
+     * Gets the proposals of the next step for the type of the previous node.
+     * 
+     * @param type
+     *            is the type of the previous node
+     * @param depth
+     *            is the depth of the script
+     * @return the proposals of the next step
+     */
+    public Object[] getCompletionProposals(Object type, int depth);
+
+    /**
+     * Validates the given call (prefix).
+     * 
+     * @param call
+     *            is the call to validate
+     * @return true if the call is valid
+     */
+    public boolean validateCall(TemplateCallExpression call);
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IScript.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IScript.java
new file mode 100644
index 0000000..42dc5c9
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IScript.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import java.io.File;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.Template;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxExceptions;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+
+/**
+ * Generator configuration.
+ * 
+ * 
+ */
+public interface IScript extends IEvalSettings {
+
+    /**
+     * Indicates if it's a default generator.
+     * 
+     * @return true if it's a default generator
+     */
+    public boolean isDefault();
+
+    /**
+     * Indicates if it's a specific generator.
+     * 
+     * @return true if it's a specific generator
+     */
+    public boolean isSpecific();
+
+    /**
+     * Reset the generator.
+     * 
+     * @throws TemplateSyntaxExceptions
+     */
+    public void reset() throws TemplateSyntaxExceptions;
+
+    /**
+     * Indicates if this generator has file template.
+     * 
+     * @return true if this generator has file template
+     */
+    public boolean hasFileTemplate();
+
+    /**
+     * Indicates if the given object has to be generated.
+     * 
+     * @param object
+     *            is the tested object
+     * @return true if the given object has to be generated
+     */
+    public boolean isGenerated(EObject object);
+
+    /**
+     * Returns the path of generation where the given object has to be
+     * generated.
+     * 
+     * @param object
+     *            is the tested object
+     * @param recursive
+     *            indicates that we use imported scripts
+     * @return the path of generation, or null if the given object isn't
+     *         generated
+     * @throws FactoryException
+     */
+    public IPath getFilePath(EObject object, boolean recursive) throws FactoryException;
+
+    /**
+     * Indicates if the generation of the given object contains errors.
+     * 
+     * @param object
+     *            is the tested object
+     * @return true if the generation of the given object contains errors
+     */
+    public boolean hasError(EObject object);
+
+    /**
+     * Gets the template with the given name for the given object of the model.
+     * In this generator, the resulting template will be applied on the given
+     * object.
+     * 
+     * @param object
+     *            is an object of the model
+     * @param key
+     *            is the name of the wanted template
+     * @return the text template
+     * @throws FactoryException
+     * @throws ENodeException
+     */
+    public Template getTextTemplateForEObject(EObject object, String key) throws FactoryException, ENodeException;
+
+    /**
+     * Gets the root template of the script for the given object.
+     * 
+     * @param object
+     *            is an object
+     * @param recursive
+     *            indicates that we use imported scripts
+     * @return the root template
+     * @throws FactoryException
+     * @throws ENodeException
+     */
+    public Template getRootTemplate(EObject object, boolean recursive) throws FactoryException, ENodeException;
+
+    /**
+     * Adds a new import. The imported elements are used, in order, after this
+     * one during generation.
+     * 
+     * @param element
+     *            to add
+     */
+    public void addImport(IEvalSettings element);
+
+    /**
+     * Removes the given import. The imported elements are used, in order, after
+     * this one during generation.
+     * 
+     * @param element
+     *            to remove
+     */
+    public void removeImport(IEvalSettings element);
+
+    /**
+     * Removes all imports. The imported elements are used, in order, after this
+     * one during generation.
+     */
+    public void clearImports();
+
+    /**
+     * Gets the main script of the specific strategy.
+     */
+    public IScript[] goToSpecifics();
+
+    /**
+     * Gets the more specific script. The specific script is used before this
+     * one to resolve the links.
+     * 
+     * @return the more specific script
+     */
+    public IScript getSpecific();
+
+    /**
+     * Sets the more specific script. The specific script is used before this
+     * one to resolve the links.
+     * 
+     * @param specific
+     *            is the more specific script
+     */
+    public void setSpecific(IScript specific);
+
+    /**
+     * Gets the script file.
+     */
+    public File getFile();
+
+    /**
+     * Returns the value to which the context of this generator maps the
+     * specified key.
+     * 
+     * @param key
+     *            whose associated value is to be returned
+     * @return the value to which the context of this generator maps the
+     *         specified key
+     */
+    public Object contextPeek(Object key);
+
+    /**
+     * Returns the value to which the context of this generator maps the
+     * specified key at the given index.
+     * 
+     * @param key
+     *            is the key
+     * @param index
+     *            is the index
+     * @return the value to which the context of this generator maps the
+     *         specified key
+     */
+    public Object contextAt(Object key, int index);
+
+    /**
+     * Associates the specified value with the specified key in the context of
+     * this generator.
+     * 
+     * @param key
+     *            with which the specified value is to be associated
+     * @param value
+     *            to be associated with the specified key
+     */
+    public void contextPush(Object key, Object value);
+
+    /**
+     * Deletes the last specified value for the specified key in the context of
+     * this generator.
+     * 
+     * @param key
+     *            is the key
+     */
+    public void contextPop(Object key);
+
+    // Context key for while index
+    public static final Integer WHILE_INDEX = new Integer(0);
+
+    // Context key for template arguments
+    public static final Integer TEMPLATE_ARGS = new Integer(1);
+
+    // Context key for service position
+    public static final Integer ARGUMENT_POSITION = new Integer(2);
+
+    // Context key for current node
+    public static final Integer CURRENT_NODE = new Integer(3);
+
+    // Context key for current node
+    public static final Integer TEMPLATE_NODE = new Integer(4);
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IScriptLoader.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IScriptLoader.java
new file mode 100644
index 0000000..2925cb1
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/IScriptLoader.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+/**
+ * A script loader that converts the script's content before loading.
+ * 
+ * 
+ */
+public interface IScriptLoader {
+
+    /**
+     * The method to convert the script's content.
+     * 
+     * @param content
+     *            is the content to convert
+     * @return the converted string
+     */
+    public String load(String content);
+
+    /**
+     * Gets the scripts of the specific strategy.
+     * 
+     * @param script
+     *            is the current script
+     */
+    public IScript[] goToSpecifics(IScript script);
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ISpecificScriptContext.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ISpecificScriptContext.java
new file mode 100644
index 0000000..da9bc45
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ISpecificScriptContext.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import java.io.File;
+
+/**
+ * The compilation context of the script hierarchy.
+ * 
+ * 
+ */
+public interface ISpecificScriptContext {
+
+    /**
+     * Gets the script for the given file.
+     * 
+     * @param file
+     *            is the script file
+     * @param chainFile
+     *            is the running chain
+     * @return the script
+     */
+    public SpecificScript getScript(File file, File chainFile);
+
+    /**
+     * Puts the given script in the context
+     * 
+     * @param file
+     *            is the script file
+     * @param script
+     *            is the script to put in the context
+     */
+    public void setScript(File file, SpecificScript script);
+
+    /**
+     * Gets the maximum level of the context. The scripts are ignored when the
+     * level is too high.
+     * 
+     * @return the maximum level of the context
+     */
+    public int getMaxLevel();
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ScriptDescriptor.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ScriptDescriptor.java
new file mode 100644
index 0000000..02c3402
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ScriptDescriptor.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * It describes a template in a specific script : name, type...
+ * <p>
+ * Sample : script type="EClass" name="template" description=""
+ * 
+ * 
+ */
+public class ScriptDescriptor {
+
+    /**
+     * The type.
+     */
+    protected String type;
+
+    /**
+     * The name.
+     */
+    protected String name;
+
+    /**
+     * The documentation.
+     */
+    protected String description;
+
+    /**
+     * The position of the file template.
+     */
+    protected Int2 fileTemplate;
+
+    /**
+     * The position of the post template expression.
+     */
+    protected Int2 postExpression;
+
+    /**
+     * The position of the script descriptor.
+     */
+    protected Int2 pos;
+
+    /**
+     * Constructor.
+     * 
+     * @param type
+     *            is the type
+     * @param name
+     *            is the name
+     */
+    public ScriptDescriptor(String type, String name) {
+        this(type, name, "", null, null); //$NON-NLS-1$
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param type
+     *            is the type
+     * @param name
+     *            is the name
+     * @param description
+     *            is the documentation
+     * @param fileTemplate
+     *            is the position of the file template
+     * @param postExpression
+     *            is the position of the post template expression
+     */
+    public ScriptDescriptor(String type, String name, String description, Int2 fileTemplate, Int2 postExpression) {
+        this.type = type;
+        this.name = name;
+        this.description = description != null ? description : ""; //$NON-NLS-1$
+        this.fileTemplate = fileTemplate;
+        this.postExpression = postExpression;
+    }
+
+    /**
+     * @return the type
+     */
+    public String getType() {
+        return type;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the documentation
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @return the position of the file template
+     */
+    public Int2 getFileTemplate() {
+        return fileTemplate;
+    }
+
+    /**
+     * @return the position of the post template expression
+     */
+    public Int2 getPostExpression() {
+        return postExpression;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof ScriptDescriptor) {
+            return type.equals(((ScriptDescriptor) other).type) && name.equals(((ScriptDescriptor) other).name);
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public int hashCode() {
+        StringBuffer key = new StringBuffer();
+        key.append(type);
+        key.append(' ');
+        key.append(name);
+        return key.toString().hashCode();
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        String type = this.type;
+        int dot = type.lastIndexOf("."); //$NON-NLS-1$
+        dot = dot > -1 ? type.substring(0, dot).lastIndexOf(".") : -1; //$NON-NLS-1$
+        if (dot > -1) {
+            type = type.substring(dot + 1);
+        }
+        StringBuffer buffer = new StringBuffer(""); //$NON-NLS-1$
+        buffer.append(TemplateConstants.SCRIPT_TYPE);
+        buffer.append(TemplateConstants.SCRIPT_PROPERTY_ASSIGN);
+        buffer.append(TemplateConstants.LITERAL[0]);
+        buffer.append(type);
+        buffer.append(TemplateConstants.LITERAL[1]);
+        buffer.append(' ');
+        buffer.append(TemplateConstants.SCRIPT_NAME);
+        buffer.append(TemplateConstants.SCRIPT_PROPERTY_ASSIGN);
+        buffer.append(TemplateConstants.LITERAL[0]);
+        buffer.append(name);
+        buffer.append(TemplateConstants.LITERAL[1]);
+        if (description != null && description.length() > 0) {
+            buffer.append(' ');
+            buffer.append(TemplateConstants.SCRIPT_DESC);
+            buffer.append(TemplateConstants.SCRIPT_PROPERTY_ASSIGN);
+            buffer.append(TemplateConstants.LITERAL[0]);
+            buffer.append(description);
+            buffer.append(TemplateConstants.LITERAL[1]);
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Returns the text to put in an outline view.
+     * 
+     * @return the text to put in an outline view
+     */
+    public String getOutlineText() {
+        StringBuffer buffer = new StringBuffer(""); //$NON-NLS-1$
+        String type = this.type;
+        int dot = type.lastIndexOf("."); //$NON-NLS-1$
+        dot = dot > -1 ? type.substring(0, dot).lastIndexOf(".") : -1; //$NON-NLS-1$
+        if (dot > -1) {
+            type = type.substring(dot + 1);
+        }
+        buffer.append(type);
+        buffer.append(" : "); //$NON-NLS-1$
+        buffer.append(name);
+        return buffer.toString();
+    }
+
+    /**
+     * Getter for the descriptor position.
+     * 
+     * @return the descriptor position
+     */
+    public Int2 getPos() {
+        return pos;
+    }
+
+    /**
+     * Setter for the descriptor position.
+     * 
+     * @param pos
+     *            descriptor position
+     */
+    public void setPos(Int2 pos) {
+        this.pos = pos;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ScriptDescriptorFactory.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ScriptDescriptorFactory.java
new file mode 100644
index 0000000..287bf73
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/ScriptDescriptorFactory.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * It is used to create a template descriptor for the given part of the text.
+ * <p>
+ * Sample : script type="EClass" name="template" description=""
+ * 
+ * 
+ */
+public class ScriptDescriptorFactory {
+
+    /**
+     * It checks the syntax and creates a descriptor for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param text
+     *            is the textual representation of the templates
+     * @param script
+     *            is the script
+     * @param limits
+     *            delimits the part of the text to be parsed for this descriptor
+     * @return the new descriptor
+     * @throws TemplateSyntaxException
+     */
+    public ScriptDescriptor createScriptDescriptor(String text, IScript script, Int2 limits) throws TemplateSyntaxException {
+        String templateType = null;
+        String templateName = null;
+        String templateDescription = null;
+        Int2 limitsFileTemplate = null;
+        Int2 limitsPostExpression = null;
+        Int2[] properties = TextSearch.getDefaultSearch().splitPositionsIn(text, limits.b(), limits.e(), TemplateConstants.SCRIPT_PROPERTIES_SEPARATORS, false, TemplateConstants.SPEC,
+                TemplateConstants.INHIBS_SCRIPT_DECLA);
+        for (int i = 0; i < properties.length; i += 2) {
+            String key = text.substring(properties[i].b(), properties[i].e());
+            if ((i + 1) < properties.length) {
+                String value = text.substring(properties[i + 1].b(), properties[i + 1].e());
+                if (value.length() >= 2 && value.startsWith(TemplateConstants.LITERAL[0]) && value.endsWith(TemplateConstants.LITERAL[1])) {
+                    value = value.substring(1, value.length() - 1);
+                    if (key.equals(TemplateConstants.SCRIPT_TYPE)) {
+                        templateType = value;
+                    } else if (key.equals(TemplateConstants.SCRIPT_NAME)) {
+                        templateName = value;
+                    } else if (key.equals(TemplateConstants.SCRIPT_DESC)) {
+                        templateDescription = value;
+                    } else if (key.equals(TemplateConstants.SCRIPT_FILE)) {
+                        limitsFileTemplate = new Int2(properties[i + 1].b() + 1, properties[i + 1].e() - 1);
+                    } else if (key.equals(TemplateConstants.SCRIPT_POST)) {
+                        limitsPostExpression = new Int2(properties[i + 1].b() + 1, properties[i + 1].e() - 1);
+                    } else {
+                        throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidKey", new Object[] { key, }), script, properties[i].b()); //$NON-NLS-1$
+                    }
+                } else {
+                    throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidKeyValue", new Object[] { key, }), script, properties[i].e()); //$NON-NLS-1$
+                }
+            } else {
+                throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingKeyValue", new Object[] { key, }), script, properties[i].e()); //$NON-NLS-1$
+            }
+        }
+        if (templateType == null) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingType"), script, limits.b()); //$NON-NLS-1$
+        }
+        if (templateName == null) {
+            throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingName"), script, limits.b()); //$NON-NLS-1$
+        }
+        ScriptDescriptor res = new ScriptDescriptor(templateType, templateName, templateDescription, limitsFileTemplate, limitsPostExpression);
+        res.setPos(limits);
+        return res;
+    }
+
+    /**
+     * Searches the region of the template in the text.
+     * 
+     * @param typeToSearch
+     *            is the type of the template to search
+     * @param nameToSearch
+     *            is the name of the template to search
+     * @return the region of the template in the text
+     */
+    public Int2 searchScriptRegion(String text, String typeToSearch, String nameToSearch) {
+        TemplateConstants.initConstants(text);
+        ScriptDescriptor descriptor = null;
+        int b = 0;
+        Int2 end = new Int2(0, 0);
+        while (end.e() > -1 && end.e() < text.length()) {
+            Int2 begin = TextSearch.getDefaultSearch().indexOf(text, TemplateConstants.SCRIPT_BEGIN, end.e(), null, TemplateConstants.INHIBS_SCRIPT_CONTENT);
+            if (begin.b() > -1) {
+                // A script
+                if (descriptor != null && typeToSearch.equals(descriptor.getType()) && nameToSearch.equals(descriptor.getName())) {
+                    return new Int2(b, begin.b());
+                }
+                // Prepare new script
+                end = TextSearch.getDefaultSearch().blockIndexEndOf(text, TemplateConstants.SCRIPT_BEGIN, TemplateConstants.SCRIPT_END, begin.b(), false, TemplateConstants.SPEC,
+                        TemplateConstants.INHIBS_SCRIPT_DECLA);
+                if (end.e() == -1) {
+                    descriptor = null;
+                } else {
+                    try {
+                        descriptor = createScriptDescriptor(text, null, new Int2(begin.e(), end.b()));
+                        b = begin.b();
+                    } catch (TemplateSyntaxException e) {
+                        descriptor = null;
+                    }
+                }
+            } else { // -1
+                // A script
+                if (descriptor != null && typeToSearch.equals(descriptor.getType()) && nameToSearch.equals(descriptor.getName())) {
+                    return new Int2(b, text.length());
+                }
+                end = new Int2(text.length(), text.length());
+            }
+        }
+        return Int2.NOT_FOUND;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/SpecificScript.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/SpecificScript.java
new file mode 100644
index 0000000..448a41a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/SpecificScript.java
@@ -0,0 +1,1664 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.Template;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxExceptions;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateText;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallSetExpression;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalJavaService;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalModel;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.JavaServiceNotFoundException;
+import org.eclipse.sirius.query.legacy.gen.template.statements.TemplateFeatureStatement;
+import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoMetamodelProvider;
+import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoModuleProvider;
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * Model specific generator configuration. A script file contains this
+ * configuration. <li>isDefault() == false</li> <li>isSpecific() == true</li>
+ * <li>hasFileTemplate() == true if more than one file template is defined in
+ * the configuration</li> <li>isGenerated(EObject) == true if one file template
+ * is defined for the object</li> <li>hasError(EObject) == false</li>
+ * 
+ * 
+ */
+public class SpecificScript extends AbstractScript {
+
+    /**
+     * Generator file extension.
+     */
+    public static final String GENERATORS_EXTENSION = "mt"; //$NON-NLS-1$
+
+    /**
+     * Should we profile the initialization of the script.
+     */
+    private boolean initProfiling = false;
+
+    /**
+     * Map of text templates.
+     */
+    protected Map textTemplates = new TreeMap(new Comparator() {
+        public int compare(Object arg0, Object arg1) {
+            if (arg0.equals(arg1)) {
+                return 0;
+            } else {
+                ScriptDescriptor a0 = (ScriptDescriptor) arg0;
+                ScriptDescriptor a1 = (ScriptDescriptor) arg1;
+                int result = a0.type.compareTo(a1.type);
+                if (result != 0) {
+                    return result;
+                } else {
+                    return a0.name.compareTo(a1.name);
+                }
+            }
+        }
+    });
+
+    /**
+     * The name of the templates.
+     */
+    protected List textTemplateNames = new ArrayList();
+
+    /**
+     * Map of file templates.
+     */
+    protected Map fileTemplates = new HashMap();
+
+    /**
+     * Script file that contains the specific configuration.
+     */
+    protected File file;
+
+    /**
+     * Root element of the metamodel.
+     */
+    protected EPackage metamodel = null;
+
+    /**
+     * Gets the text template that corresponds to a file template.
+     */
+    protected Map file2TextTemplate = new HashMap();
+
+    /**
+     * Gets the file template that corresponds to a text template.
+     */
+    protected Map text2FileTemplate = new HashMap();
+
+    /**
+     * The chain file.
+     */
+    protected File chainFile = null;
+
+    /**
+     * The context of the script.
+     */
+    protected ISpecificScriptContext scriptContext = null;
+
+    /**
+     * Constructor.
+     */
+    public SpecificScript() {
+        super();
+        this.file = null;
+        try {
+            init(new ArrayList(), "", false); //$NON-NLS-1$
+        } catch (final TemplateSyntaxExceptions e) {
+            // Never catch
+        }
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param file
+     *            is the script file that contains the specific configuration
+     */
+    public SpecificScript(File file) {
+        this(file, null);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param file
+     *            is the script file that contains the specific configuration
+     * @param chainFile
+     *            is the optional chain file
+     */
+    public SpecificScript(File file, File chainFile) {
+        this();
+        this.file = file;
+        this.chainFile = chainFile;
+        this.scriptContext = null;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param file
+     *            is the script file that contains the specific configuration
+     * @param chainFile
+     *            is the optional chain file
+     * @param scriptContext
+     *            is the context of the script
+     */
+    public SpecificScript(File file, File chainFile, ISpecificScriptContext scriptContext) {
+        this();
+        this.file = file;
+        this.chainFile = chainFile;
+        this.scriptContext = scriptContext;
+        if (scriptContext != null) {
+            scriptContext.setScript(file, this);
+        }
+    }
+
+    /**
+     * @return the root element of the metamodel or null
+     */
+    public EPackage getMetamodel() {
+        return metamodel;
+    }
+
+    /**
+     * @return the map of text templates
+     */
+    public Map getTextTemplates() {
+        return textTemplates;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public File getFile() {
+        return file;
+    }
+
+    /**
+     * @return the chain file
+     */
+    public File getChainFile() {
+        return chainFile;
+    }
+
+    /**
+     * @param chainFile
+     *            is the chain file
+     */
+    public void setChainFile(File chainFile) {
+        this.chainFile = chainFile;
+    }
+
+    /* (non-Javadoc) */
+    public boolean isDefault() {
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    public boolean isSpecific() {
+        return true;
+    }
+
+    /* (non-Javadoc) */
+    public void reset() throws TemplateSyntaxExceptions {
+        reset(new ArrayList());
+    }
+
+    private void reset(List fileHierarchy) throws TemplateSyntaxExceptions {
+        if (file != null) {
+            final String content = Resources.getFileContent(file).toString();
+            reset(fileHierarchy, content);
+        }
+    }
+
+    /**
+     * Reset the generator.
+     * 
+     * @param content
+     *            is the new content to be parsed
+     * @throws TemplateSyntaxExceptions
+     */
+    public void reset(String content) throws TemplateSyntaxExceptions {
+        reset(new ArrayList(), content);
+    }
+
+    /**
+     * Reset the generator.
+     * 
+     * @param fileHierarchy
+     *            is the imported scripts hierarchy
+     * @param content
+     *            is the new content to be parsed
+     * @throws TemplateSyntaxExceptions
+     */
+    private synchronized void reset(List fileHierarchy, String content) throws TemplateSyntaxExceptions {
+        if (file != null) {
+            if (fileHierarchy.contains(file.getAbsolutePath())) {
+                final List problems = new ArrayList();
+                problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.RecursiveDependency"), this, 0)); //$NON-NLS-1$
+                throw new TemplateSyntaxExceptions(problems);
+            } else {
+                fileHierarchy.add(file.getAbsolutePath());
+            }
+        }
+        boolean checkOnly;
+        if (oldContent == null || !oldContent.equals(content)) {
+            oldContent = content;
+            checkOnly = false;
+            textTemplates.clear();
+            textTemplateNames.clear();
+            fileTemplates.clear();
+            id2TextTemplate.clear();
+            id2FileTemplate.clear();
+            file2TextTemplate.clear();
+            text2FileTemplate.clear();
+            quickTemplates.clear();
+        } else {
+            checkOnly = true;
+        }
+        clearFoundProperties();
+        current = null;
+        init(fileHierarchy, content, checkOnly);
+
+    }
+
+    private String oldContent = null;
+
+    /**
+     * Gets the file template for the given text template.
+     * 
+     * @param textTemplate
+     *            is a text template
+     * @return the file template
+     */
+    public Template getFileTemplate(Template textTemplate) {
+        return (Template) text2FileTemplate.get(textTemplate);
+
+    }
+
+    /**
+     * Gets the text template for the given file template.
+     * 
+     * @param fileTemplate
+     *            is a file template
+     * @return the text template
+     */
+    public Template getTextTemplate(Template fileTemplate) {
+        return (Template) file2TextTemplate.get(fileTemplate);
+    }
+
+    /* (non-Javadoc) */
+    public Template getTextTemplateForEObject(EObject object, String name) throws FactoryException, ENodeException {
+        return getTextTemplateForEClass(object.eClass(), name);
+    }
+
+    private Template getTextTemplateForEClass(EClass eClass, String name) throws FactoryException, ENodeException {
+        Template template = getTextTemplateForEClassifier(eClass, name);
+        if (template == null) {
+            if (eClass.getESuperTypes().isEmpty() && eClass != EcorePackage.eINSTANCE.getEObject()) {
+                /*
+                 * We want to add an "artificial" specialization on EObject
+                 */
+                template = getTextTemplateForEClass(EcorePackage.eINSTANCE.getEObject(), name);
+            }
+            final Iterator superTypes = eClass.getESuperTypes().iterator();
+            while (template == null && superTypes.hasNext()) {
+                final EClassifier superType = (EClassifier) superTypes.next();
+                if (superType instanceof EClass) {
+                    template = getTextTemplateForEClass((EClass) superType, name);
+                } else {
+                    template = getTextTemplateForEClassifier(superType, name);
+                }
+            }
+        }
+        return template;
+    }
+
+    private Template getTextTemplateForEClassifier(EClassifier eClass, String name) throws FactoryException, ENodeException {
+        final ScriptDescriptor key = new ScriptDescriptor(ETools.getEClassifierPath(eClass), name);
+        Template template = (Template) id2TextTemplate.get(key);
+        if (template == null) {
+            template = (Template) textTemplates.get(key);
+            if (template == null) {
+                final Iterator it = textTemplates.entrySet().iterator();
+                while (template == null && it.hasNext()) {
+                    final Map.Entry entry = (Map.Entry) it.next();
+                    if (name.equals(((ScriptDescriptor) entry.getKey()).name) && ('.' + key.type).endsWith('.' + ((ScriptDescriptor) entry.getKey()).type)) {
+                        template = (Template) entry.getValue();
+                    }
+                }
+            }
+            if (template != null) {
+                id2TextTemplate.put(key, template);
+            }
+        }
+        return template;
+    }
+
+    /* (non-Javadoc) */
+    public Template getRootTemplate(EObject object, boolean recursive) throws FactoryException, ENodeException {
+        Template textTemplate = null;
+        final Template fileTemplate = getFileTemplateForEObject(object);
+        if (fileTemplate != null) {
+            textTemplate = (Template) file2TextTemplate.get(fileTemplate);
+        }
+        if (recursive && !hasFileTemplate()) {
+            if (textTemplate == null) {
+                final Iterator imports = this.imports.iterator();
+                while (textTemplate == null && imports.hasNext()) {
+                    final IEvalSettings anImport = (IEvalSettings) imports.next();
+                    if (anImport instanceof IScript) {
+                        try {
+                            textTemplate = ((IScript) anImport).getRootTemplate(object, false);
+                        } catch (final ENodeException e) {
+                            textTemplate = null;
+                        }
+                    }
+                }
+            }
+        }
+        if (textTemplate != null) {
+            return textTemplate;
+        } else {
+            throw new ENodeException(AcceleoGenMessages.getString("ENodeError.UnresolvedRoot"), new Int2(0, 0), this, object, true); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Gets the text template that corresponds to an identifiant.
+     */
+    protected Map id2TextTemplate = new HashMap();
+
+    /**
+     * Creates a new empty text template.
+     * 
+     * @param descriptor
+     *            is the descriptor of the template
+     * @return the new text template
+     * @throws TemplateSyntaxException
+     */
+    public Template createTextTemplate(ScriptDescriptor descriptor) throws TemplateSyntaxException {
+        return createTextTemplate(descriptor, "", new Int2(0, 0)); //$NON-NLS-1$
+    }
+
+    /**
+     * Creates a new text template.
+     * 
+     * @param descriptor
+     *            is the descriptor of the template
+     * @param text
+     *            is the content of the file
+     * @param pos
+     *            is the position of the template in the file
+     * @return the new text template
+     * @throws TemplateSyntaxException
+     *             if the text has syntax errors
+     */
+    public Template createTextTemplate(ScriptDescriptor descriptor, String text, Int2 pos) throws TemplateSyntaxException {
+        TemplateSyntaxException failure = null;
+        Template template = (Template) textTemplates.get(descriptor);
+        if (template == null) {
+            // Template has been created before?
+            final String quickEntry = descriptor.getType() + '\n' + descriptor.getName() + '\n' + text.substring(pos.b(), pos.e());
+            template = (Template) quickTemplates.get(quickEntry);
+            if (template == null) {
+                // Create template
+                try {
+                    template = newTextTemplate(descriptor, text, pos);
+                } catch (final TemplateSyntaxException e) {
+                    template = newTextTemplate(descriptor, null, pos);
+                    failure = e;
+                }
+                quickTemplates.put(quickEntry, template);
+            }
+            // Update the position of this template in the script file
+            template.setPos(pos);
+            textTemplates.put(descriptor, template);
+            if (!textTemplateNames.contains(descriptor.getName())) {
+                textTemplateNames.add(descriptor.getName());
+            }
+            current = template;
+        } else {
+            failure = new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateEntry.Text", new Object[] { descriptor.toString(), }), this, pos); //$NON-NLS-1$
+        }
+        if (failure != null) {
+            throw failure;
+        }
+        return template;
+    }
+
+    private final Map quickTemplates = new HashMap();
+
+    /**
+     * It checks the syntax and creates a template for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param descriptor
+     *            is the descriptor of the template
+     * @param text
+     *            is the textual representation of the script that contains
+     *            templates
+     * @param pos
+     *            delimits the part of the text to be parsed for this template
+     * @return the new template
+     * @throws TemplateSyntaxException
+     */
+    protected Template newTextTemplate(ScriptDescriptor descriptor, String text, Int2 pos) throws TemplateSyntaxException {
+        final Template template = Template.read(text, pos, this);
+        template.setDescriptor(descriptor);
+        return template;
+    }
+
+    /**
+     * Last template created.
+     */
+    protected Template current = null;
+
+    /**
+     * @return last template created
+     */
+    public Template getCurrent() {
+        return current;
+    }
+
+    /**
+     * @param current
+     *            is the last template created
+     */
+    public void setCurrent(Template current) {
+        this.current = current;
+    }
+
+    /* (non-Javadoc) */
+    public boolean hasFileTemplate() {
+        return fileTemplates.size() > 0;
+    }
+
+    /* (non-Javadoc) */
+    public boolean isGenerated(EObject object) {
+        try {
+            return getFilePath(object, true) != null;
+        } catch (final FactoryException e) {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc) */
+    public IPath getFilePath(EObject object, boolean recursive) throws FactoryException {
+        if (hasFileTemplate()) {
+            try {
+                final Template fileTemplate = getFileTemplateForEObject(object);
+                if (fileTemplate != null) {
+                    final String path = fileTemplate.evaluateAsString(object, LaunchManager.create("run", false)).trim(); //$NON-NLS-1$
+                    if (path.length() > 0) {
+                        return new Path(path);
+                    }
+                }
+            } catch (final ENodeException e) {
+            }
+        } else if (recursive) {
+            final Iterator imports = this.imports.iterator();
+            while (imports.hasNext()) {
+                final IEvalSettings anImport = (IEvalSettings) imports.next();
+                if (anImport instanceof IScript) {
+                    final IPath path = ((IScript) anImport).getFilePath(object, false);
+                    if (path != null) {
+                        return path;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets the file template for the given object of the model.
+     * 
+     * @param object
+     *            is an object of the model
+     * @return the file template
+     */
+    public Template getFileTemplateForEObject(EObject object) {
+        Template res = getFileTemplateForEClass(object.eClass());
+        // try the default EObject type
+        if (res == null) {
+            res = getFileTemplateForEClass(EcorePackage.eINSTANCE.getEObject());
+        }
+        return res;
+
+    }
+
+    private Template getFileTemplateForEClass(EClass eClass) {
+        Template template = getFileTemplateForEClassifier(eClass);
+        if (template == null) {
+            final Iterator superTypes = eClass.getESuperTypes().iterator();
+            while (template == null && superTypes.hasNext()) {
+                final EClassifier superType = (EClassifier) superTypes.next();
+                if (superType instanceof EClass) {
+                    template = getFileTemplateForEClass((EClass) superType);
+                } else {
+                    template = getFileTemplateForEClassifier(superType);
+                }
+            }
+        }
+        return template;
+    }
+
+    private Template getFileTemplateForEClassifier(EClassifier eClass) {
+        final String typeID = ETools.getEClassifierPath(eClass);
+        Template template = (Template) id2FileTemplate.get(typeID);
+        if (template == null) {
+            template = (Template) fileTemplates.get(typeID);
+            if (template == null) {
+                final Iterator it = fileTemplates.entrySet().iterator();
+                while (template == null && it.hasNext()) {
+                    final Map.Entry entry = (Map.Entry) it.next();
+                    if (('.' + typeID).endsWith("." + entry.getKey())) { //$NON-NLS-1$
+                        template = (Template) entry.getValue();
+                    }
+                }
+            }
+            if (template != null) {
+                id2FileTemplate.put(typeID, template);
+            }
+        }
+        return template;
+    }
+
+    /**
+     * Gets the file template that corresponds to an identifiant.
+     */
+    protected Map id2FileTemplate = new HashMap();
+
+    /**
+     * Creates a new file template.
+     * 
+     * @param typeID
+     *            is the identifiant
+     * @param text
+     *            is the content of the template
+     * @param textTemplate
+     *            is the text template that corresponds to the file template to
+     *            be created
+     * @throws TemplateSyntaxException
+     */
+    public void createFileTemplate(String typeID, String text, Template textTemplate) throws TemplateSyntaxException {
+        createFileTemplate(typeID, text, new Int2(0, text.length()), textTemplate);
+    }
+
+    /**
+     * Creates a new file template.
+     * 
+     * @param typeID
+     *            is the identifiant
+     * @param text
+     *            is the content of the file
+     * @param pos
+     *            is the position of the template in the file
+     * @param textTemplate
+     *            is the text template that corresponds to the file template to
+     *            be created
+     * @throws TemplateSyntaxException
+     */
+    public void createFileTemplate(String typeID, String text, Int2 pos, Template textTemplate) throws TemplateSyntaxException {
+        TemplateSyntaxException failure = null;
+        Template template = (Template) fileTemplates.get(typeID);
+        if (template == null) {
+            try {
+                template = Template.read(text, pos, this);
+            } catch (final TemplateSyntaxException e) {
+                template = new Template(this);
+                failure = e;
+            }
+            fileTemplates.put(typeID, template);
+            file2TextTemplate.put(template, textTemplate);
+            text2FileTemplate.put(textTemplate, template);
+        } else {
+            failure = new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateEntry.File", new Object[] { typeID, }), this, pos); //$NON-NLS-1$
+        }
+        if (failure != null) {
+            throw failure;
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        final StringBuffer buffer = new StringBuffer(super.toString());
+        final Iterator it = textTemplates.entrySet().iterator();
+        while (it.hasNext()) {
+            final Map.Entry entry = (Map.Entry) it.next();
+            final ScriptDescriptor key = (ScriptDescriptor) entry.getKey();
+            buffer.append(TemplateConstants.SCRIPT_BEGIN); // TemplateConstants.
+            // SCRIPT_BEGIN
+            // ends with " "
+            buffer.append(key.toString());
+            // File template?
+            final Template fileTemplate = (Template) fileTemplates.get(key.type);
+            if (fileTemplate != null) {
+                buffer.append(' ');
+                buffer.append(TemplateConstants.SCRIPT_FILE);
+                buffer.append(TemplateConstants.SCRIPT_PROPERTY_ASSIGN);
+                buffer.append(TemplateConstants.LITERAL[0]);
+                buffer.append(fileTemplate.toString());
+                buffer.append(TemplateConstants.LITERAL[1]);
+            }
+            buffer.append(TemplateConstants.SCRIPT_END);
+            buffer.append('\n');
+            final String text = ((Template) entry.getValue()).toString();
+            buffer.append(text);
+            buffer.append("\n\n"); //$NON-NLS-1$
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * It checks the syntax and creates templates for the given text.
+     * 
+     * @param fileHierarchy
+     *            is the imported scripts hierarchy
+     * @param text
+     *            is the text to be parsed
+     * @param checkOnly
+     *            indicates if it checks the syntax only
+     * @throws TemplateSyntaxExceptions
+     */
+    protected void init(List fileHierarchy, String text, boolean checkOnly) throws TemplateSyntaxExceptions {
+        final boolean isRoot = fileHierarchy.size() <= 1;
+        if (AbstractScript.getScriptLoader() != null) {
+            text = AbstractScript.getScriptLoader().load(text);
+            if (text != null) {
+                final List problems = new ArrayList();
+                TemplateConstants.initConstants(text);
+                oldImports = new ArrayList(imports);
+                clearImports();
+                if (text != null && text.length() > 0) {
+                    // Get imports
+                    if (file != null) {
+                        try {
+                            addImport(new EvalJavaService(file));
+                        } catch (final JavaServiceNotFoundException e) {
+                        }
+                    }
+                    parseImports(fileHierarchy, text, problems);
+                    getSystemServicesFactory().addImports(this, isRoot);
+                    // Parse scripts
+                    if (!checkOnly) {
+                        syntaxErrors.clear();
+                        parseScripts(text, syntaxErrors);
+                    }
+                    problems.addAll(syntaxErrors);
+                }
+                // Check all expressions of the generator
+                if (file != null) {
+                    final IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath()));
+                    if (workspaceFile != null && workspaceFile.exists()) {
+                        if (isRoot) {
+                            checkAllExpressions(problems);
+                        }
+                    }
+                }
+                // check only if the compilation result is not for runtime use
+                if (scriptContext != null && scriptContext.getMaxLevel() != -1) {
+                    checkOverride(problems);
+                }
+                // Throw TemplateSyntaxExceptions if problems are detected
+                if (problems.size() > 0) {
+                    throw new TemplateSyntaxExceptions(problems);
+                }
+            }
+        }
+    }
+
+    /**
+     * Check for masked overrides.
+     * 
+     * @param problems
+     *            the problem list
+     */
+    private void checkOverride(List problems) {
+        Map overrides = new HashMap();
+
+        Iterator it = getImports().iterator();
+        while (it.hasNext()) {
+            Map localOverrides = new HashMap();
+            IEvalSettings imp = (IEvalSettings) it.next();
+            if (imp instanceof SpecificScript) {
+                SpecificScript script = (SpecificScript) imp;
+                final Iterator entries = script.textTemplates.entrySet().iterator();
+                while (entries.hasNext()) {
+                    final Map.Entry entry = (Map.Entry) entries.next();
+                    final EClassifier type = ETools.getEClassifier(script.getMetamodel(), ((ScriptDescriptor) entry.getKey()).getType());
+                    if (type instanceof EClass) {
+                        final Template template = (Template) entry.getValue();
+                        final String name = template.getDescriptor().getName();
+                        List typeList = (List) overrides.get(name);
+                        if (typeList == null) {
+                            typeList = new ArrayList();
+                            localOverrides.put(name, typeList);
+                        } else {
+                            if (isMaskedOverride((EClass) type, typeList)) {
+                                TemplateSyntaxException problem = new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.BadOverride",
+                                        new Object[] { fileScriptToImportString(script.getFile()), }), this, 1);
+                                problem.setSeverity(IMarker.SEVERITY_WARNING);
+                                problems.add(problem);
+                            }
+                        }
+                        typeList.add(type);
+                    }
+                }
+            }
+            // merge localOverrides and overrides
+            Iterator localIt = localOverrides.entrySet().iterator();
+            while (localIt.hasNext()) {
+                final Map.Entry entry = (Map.Entry) localIt.next();
+                String name = (String) entry.getKey();
+                List types = (List) overrides.get(name);
+                if (types == null) {
+                    overrides.put(name, entry.getValue());
+                } else {
+                    types.addAll((List) entry.getValue());
+                }
+            }
+        }
+    }
+
+    private boolean isMaskedOverride(EClass type, List typeList) {
+        boolean res = false;
+        List supertypes = type.getEAllSuperTypes();
+        Iterator it = typeList.iterator();
+        while (!res && it.hasNext()) {
+            res = supertypes.contains(it.next());
+        }
+        return res;
+    }
+
+    private final List syntaxErrors = new ArrayList();
+
+    /**
+     * It checks the syntax and creates the scripts for the given text.
+     * 
+     * @param text
+     *            is the text to be parsed
+     * @param problems
+     *            are the syntax problems detected during this parsing
+     */
+    private void parseScripts(String text, List problems) {
+        TemplateConstants.initConstants(text);
+        ScriptDescriptor descriptor = null;
+        Int2 end = new Int2(0, 0);
+        while (end.e() > -1 && end.e() < text.length()) {
+            final Int2 begin = TextSearch.getDefaultSearch().indexOf(text, TemplateConstants.SCRIPT_BEGIN, end.e(), null, TemplateConstants.INHIBS_SCRIPT_CONTENT);
+            if (begin.b() > -1) {
+                // Create a new script
+                try {
+                    newScript(descriptor, text, new Int2(end.e(), begin.b()));
+                } catch (final TemplateSyntaxException e) {
+                    problems.add(e);
+                }
+                // Clear informations
+                descriptor = null;
+                // Prepare new script
+                end = TextSearch.getDefaultSearch().blockIndexEndOf(text, TemplateConstants.SCRIPT_BEGIN, TemplateConstants.SCRIPT_END, begin.b(), false, TemplateConstants.SPEC,
+                        TemplateConstants.INHIBS_SCRIPT_DECLA);
+                if (end.e() == -1) {
+                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingScriptEndTag"), this, begin.b())); //$NON-NLS-1$
+                } else {
+                    try {
+                        descriptor = getDescriptorFactory().createScriptDescriptor(text, this, new Int2(begin.e(), end.b()));
+                    } catch (final TemplateSyntaxException e) {
+                        problems.add(e);
+                        descriptor = null;
+                    }
+                }
+            } else { // -1
+                // Create a new script
+                try {
+                    newScript(descriptor, text, new Int2(end.e(), text.length()));
+                } catch (final TemplateSyntaxException e) {
+                    problems.add(e);
+                }
+                end = new Int2(text.length(), text.length());
+            }
+        }
+    }
+
+    /**
+     * Creates an instance of the descriptor factory. This new factory will be
+     * used to create template's descriptors.
+     * 
+     * @return the new factory
+     */
+    protected ScriptDescriptorFactory createDescriptorFactory() {
+        return new ScriptDescriptorFactory();
+    }
+
+    /**
+     * Gets the instance of the descriptor factory. This factory is used to
+     * create template's descriptors.
+     * 
+     * @return the descriptor factory
+     */
+    private ScriptDescriptorFactory getDescriptorFactory() {
+        if (descriptorFactory == null) {
+            descriptorFactory = createDescriptorFactory();
+        }
+        return descriptorFactory;
+    }
+
+    private ScriptDescriptorFactory descriptorFactory = null;
+
+    /**
+     * It checks the syntax and creates the imports for the given text.
+     * 
+     * @param fileHierarchy
+     *            is the imported scripts hierarchy
+     * @param text
+     *            is the text to be parsed
+     * @param problems
+     *            are the syntax problems detected during this parsing
+     */
+    protected void parseImports(List fileHierarchy, String text, List problems) {
+        metamodel = null;
+        final List importValues = new ArrayList();
+        int end = TextSearch.getDefaultSearch().indexOf(text, TemplateConstants.SCRIPT_BEGIN, 0, null, TemplateConstants.INHIBS_SCRIPT_CONTENT).b();
+        if (end == -1) {
+            end = text.length();
+        }
+        int pos = 0;
+        while (pos > -1 && pos < end) {
+            final Int2 bComment = TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.COMMENT_BEGIN, pos, end);
+            final Int2 bImports = TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.IMPORT_BEGIN, pos, end);
+            if (bComment.b() > -1 && (bImports.b() == -1 || bComment.b() <= bImports.b())) {
+                final Int2 eComment = TextSearch.getDefaultSearch().blockIndexEndIn(text, TemplateConstants.COMMENT_BEGIN, TemplateConstants.COMMENT_END, bComment.b(), end, false);
+                if (eComment.b() > -1) {
+                    pos = eComment.e();
+                } else {
+                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingCommentEndTag"), this, bComment.b())); //$NON-NLS-1$
+                    pos = end;
+                }
+            } else if (bImports.b() > -1) {
+                final Int2 eImports = TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.IMPORT_END, bImports.e(), end);
+                if (eImports.b() > -1) {
+                    final Int2[] imports = TextSearch.getDefaultSearch().splitPositionsIn(text, bImports.e(), eImports.b(), new String[] { "\n" }, false); //$NON-NLS-1$
+                    for (Int2 import1 : imports) {
+                        Int2 importPos = import1;
+                        importPos = TextSearch.getDefaultSearch().trim(text, importPos.b(), importPos.e());
+                        if (importPos.b() > -1) {
+                            if (importPos.e() > importPos.b()) {
+                                if (TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.IMPORT_WORD, importPos.b(), importPos.e()).b() == importPos.b()) {
+                                    final Int2 valuePos = TextSearch.getDefaultSearch().trim(text, importPos.b() + TemplateConstants.IMPORT_WORD.length(), importPos.e());
+                                    if (valuePos.b() > -1) {
+                                        final String value = text.substring(valuePos.b(), valuePos.e()).trim();
+                                        if (importValues.contains(value)) {
+                                            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateValue", new Object[] { "import", }), this, valuePos)); //$NON-NLS-1$ //$NON-NLS-2$
+                                        } else {
+                                            importValues.add(value);
+                                            try {
+                                                newImport(fileHierarchy, value, valuePos, importValues.size());
+                                            } catch (final TemplateSyntaxException e) {
+                                                problems.add(e);
+                                            }
+                                        }
+                                    } else {
+                                        problems.add(new TemplateSyntaxException(
+                                                AcceleoGenMessages.getString("TemplateSyntaxError.EmptyImport"), this, importPos.b() + TemplateConstants.IMPORT_WORD.length())); //$NON-NLS-1$
+                                    }
+                                } else if (TextSearch.getDefaultSearch().indexIn(text, TemplateConstants.MODELTYPE_WORD, importPos.b(), importPos.e()).b() == importPos.b()) {
+                                    final Int2 valuePos = TextSearch.getDefaultSearch().trim(text, importPos.b() + TemplateConstants.MODELTYPE_WORD.length(), importPos.e());
+                                    if (valuePos.b() > -1) {
+                                        final String value = text.substring(valuePos.b(), valuePos.e()).trim();
+                                        if (importValues.contains(value)) {
+                                            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.DuplicateValue", new Object[] { "metamodel", }), this, valuePos)); //$NON-NLS-1$ //$NON-NLS-2$
+                                        } else {
+                                            importValues.add(value);
+                                            try {
+                                                newImport(fileHierarchy, value, valuePos, importValues.size());
+                                            } catch (final TemplateSyntaxException e) {
+                                                problems.add(e);
+                                            }
+                                        }
+                                    } else {
+                                        problems.add(new TemplateSyntaxException(
+                                                AcceleoGenMessages.getString("TemplateSyntaxError.EmptyValue", new Object[] { "metamodel", }), this, importPos.b() + TemplateConstants.MODELTYPE_WORD.length())); //$NON-NLS-1$ //$NON-NLS-2$
+                                    }
+                                } else {
+                                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingKeyWord", new Object[] { "import", }), this, importPos.b())); //$NON-NLS-1$ //$NON-NLS-2$
+                                }
+                            }
+                        }
+                    }
+                    pos = eImports.e();
+                } else {
+                    problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidImportSequence"), this, bImports.b())); //$NON-NLS-1$
+                    pos = end;
+                }
+            } else {
+                pos = end;
+            }
+        }
+    }
+
+    /**
+     * Creates an import.
+     * 
+     * @param fileHierarchy
+     *            is the imported scripts hierarchy
+     * @param value
+     *            is the import value
+     * @param valuePos
+     *            is the position of the value in the script
+     * @param num
+     *            is the number of the import
+     * @throws TemplateSyntaxException
+     */
+    private void newImport(List fileHierarchy, String value, Int2 valuePos, int num) throws TemplateSyntaxException {
+        boolean isMetamodelImport = parseMetamodelImport(value, valuePos, num);
+        if (scriptContext == null || scriptContext.getMaxLevel() == -1 || fileHierarchy.size() < scriptContext.getMaxLevel()) {
+            if (!isMetamodelImport) {
+                if (file != null) {
+                    boolean service = false;
+                    boolean specificExists = false;
+                    // Specific script file
+                    final String[] specificExtensions = getSpecificImportExtensions();
+                    for (String specificExtension : specificExtensions) {
+                        final File specificFile = resolveScriptFile(file, value, specificExtension);
+                        if (specificFile != null && specificFile.exists()) {
+                            // Is recursive import?
+                            IScript genSpecific = this;
+                            do {
+                                if (genSpecific.getFile() != null && genSpecific.getFile().equals(specificFile)) {
+                                    throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.RecursiveImport"), this, valuePos); //$NON-NLS-1$
+                                }
+                                genSpecific = genSpecific.getSpecific();
+                            } while (genSpecific != null);
+                            // Add import
+                            try {
+                                if (!tryOptimizedImport(fileHierarchy, specificFile)) {
+                                    final SpecificScript newImport = createSpecificImport(specificFile);
+                                    newImport.setInitProfiling(initProfiling);
+                                    newImport.reset(new ArrayList(fileHierarchy));
+                                    newImport.setSpecific(this);
+                                    addImport(newImport);
+                                }
+                            } catch (final TemplateSyntaxExceptions e) {
+                                String message = AcceleoGenMessages.getString("SpecificScript.ErroneousTemplate"); //$NON-NLS-1$
+                                if (e.getProblems().size() == 1) {
+                                    message += " : " + ((TemplateSyntaxException) e.getProblems().get(0)).getMessage(); //$NON-NLS-1$
+                                }
+                                throw new TemplateSyntaxException(message, this, valuePos);
+                            }
+                            specificExists = true;
+                        }
+                    }
+                    // Java service
+                    try {
+
+                        addImportForJavaService(file, value);
+                        service = true;
+                    } catch (final JavaServiceNotFoundException e) {
+                        // throw new
+                        // TemplateSyntaxException(e.getMessage(),this,valuePos);
+                    }
+                    if (!service && !specificExists) {
+                        throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedImport", new Object[] { value, }), this, valuePos); //$NON-NLS-1$
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Add a java service to import list.
+     * 
+     * @param file
+     *            the current script file
+     * @param value
+     *            the class name
+     * @throws JavaServiceNotFoundException
+     *             if the class designed by value doesn't exists
+     */
+    protected void addImportForJavaService(final File file, final String value) throws JavaServiceNotFoundException {
+        addImport(new EvalJavaService(file, value));
+    }
+
+    protected File resolveScriptFile(File script, String importValue, String extension) {
+
+        File res = null;
+        final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(script.getAbsolutePath()));
+        if (file != null && file.isAccessible()) {
+            final IPath importPath = new Path(importValue.replaceAll("\\.", "/")).addFileExtension(extension); //$NON-NLS-1$ //$NON-NLS-2$
+            res = getScriptFileInProject(file.getProject(), importPath);
+        } else {
+            final String pluginId = AcceleoModuleProvider.getDefault().getPluginId(script);
+            if (pluginId != null) {
+                final Bundle bundle = Platform.getBundle(pluginId);
+                if (bundle != null) {
+                    res = AcceleoModuleProvider.getDefault().getFile(bundle.getSymbolicName(), importValue, extension);
+                }
+            }
+        }
+
+        return res;
+    }
+
+    private String fileScriptToImportString(File script) {
+        String res = "";
+        final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(script.getAbsolutePath()));
+        String[] segments = file.getProjectRelativePath().segments();
+        for (int i = 1; i < segments.length; ++i) {
+            res += segments[i];
+            if (i < segments.length - 1) {
+                res += "."; //$NON-NLS-1$
+            }
+        }
+        return res;
+    }
+
+    private File getScriptFileInProject(IProject project, IPath importPath) {
+        File result = null;
+        if (project.exists()) {
+            try {
+                final IJavaProject javaProject = JavaCore.create(project);
+                final IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
+                for (int i = 0; i < entries.length && result == null; i++) {
+                    final IClasspathEntry entry = entries[i];
+                    if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE && entry.getPath().segmentCount() > 1) {
+                        final IFile test = ResourcesPlugin.getWorkspace().getRoot().getFile(entry.getPath().append(importPath));
+                        if (test.exists()) {
+                            result = test.getLocation().toFile();
+                        }
+                    }
+                }
+                for (int i = 0; i < entries.length && result == null; i++) {
+                    final IClasspathEntry entry = entries[i];
+                    if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT && entry.getPath().segmentCount() == 1) {
+                        final IProject entryProject = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().segment(0));
+                        if (entryProject != null && entryProject.exists()) {
+                            result = getScriptFileInProject(entryProject, importPath);
+                        }
+                    }
+                }
+            } catch (final JavaModelException e) {
+                result = null;
+            }
+            if (result == null) {
+                final String[] requiredPluginIDs = Resources.getRequiredPluginIDs(project);
+                for (int i = 0; i < requiredPluginIDs.length && result == null; i++) {
+                    final IProject bundleProject = ResourcesPlugin.getWorkspace().getRoot().getProject(requiredPluginIDs[i]);
+                    if (bundleProject != null && bundleProject.exists()) {
+                        result = getScriptFileInProject(bundleProject, importPath);
+                    } else if (Platform.getBundle(requiredPluginIDs[i]) != null) {
+                        result = AcceleoModuleProvider.getDefault().getFile(requiredPluginIDs[i], importPath);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Tries to parse the import value and creates a metamodel import.
+     * 
+     * @param value
+     *            is the import value
+     * @param valuePos
+     *            is the position of the value in the script
+     * @param num
+     *            is the number of the import
+     * @return true if a metamodel import has been created
+     * @throws TemplateSyntaxException
+     */
+    protected boolean parseMetamodelImport(String value, Int2 valuePos, int num) throws TemplateSyntaxException {
+        if (num == 1) {
+            value = value.trim();
+            final EPackage regValue = EPackage.Registry.INSTANCE.getEPackage(value);
+            if (regValue != null) {
+                final EvalModel anImport = new EvalModel(value);
+                if (anImport.getMetamodel() == null) {
+                    throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedMetamodel"), this, valuePos); //$NON-NLS-1$
+                }
+                metamodel = anImport.getMetamodel();
+                addImport(anImport);
+                return true;
+            } else {
+                IPath ecorePath = new Path(value);
+                if (ecorePath.segmentCount() >= 2) {
+                    ecorePath = ecorePath.removeFileExtension().addFileExtension("ecore"); //$NON-NLS-1$
+                }
+                final File ecoreFile = AcceleoMetamodelProvider.getDefault().getFile(ecorePath);
+                if (ecoreFile != null && ecoreFile.exists()) {
+                    final EvalModel anImport = new EvalModel(value);
+                    if (anImport.getMetamodel() == null) {
+                        throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedMetamodel"), this, valuePos); //$NON-NLS-1$
+                    }
+                    metamodel = anImport.getMetamodel();
+                    addImport(anImport);
+                    return true;
+                } else {
+                    throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedMetamodel"), this, valuePos); //$NON-NLS-1$
+                }
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Gets all the file extensions that are accepted in the imports.
+     * 
+     * @return a table of extensions
+     */
+    protected String[] getSpecificImportExtensions() {
+        return new String[] { SpecificScript.GENERATORS_EXTENSION };
+    }
+
+    /**
+     * Creates a specific import for the given file.
+     * 
+     * @param specificFile
+     *            is the file to import
+     * @return the new specific import
+     */
+    protected SpecificScript createSpecificImport(File specificFile) {
+        if (scriptContext != null) {
+            final SpecificScript result = scriptContext.getScript(specificFile, chainFile);
+            if (result != null) {
+                return result;
+            }
+        }
+        final SpecificScript result = new SpecificScript(specificFile, chainFile, scriptContext);
+        return result;
+    }
+
+    /**
+     * Tries a quick import with the file modification stamp.
+     * 
+     * @param fileHierarchy
+     *            is the imported scripts hierarchy
+     * @param file
+     *            is the file to import
+     * @return true if the quick import is done
+     * @throws TemplateSyntaxExceptions
+     */
+    private boolean tryOptimizedImport(List fileHierarchy, File file) throws TemplateSyntaxExceptions {
+        boolean tryOptimizedImport;
+        final IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath()));
+        if (workspaceFile != null && workspaceFile.isAccessible()) {
+            final Double newModificationStamp = new Double(workspaceFile.getModificationStamp());
+            final Double oldModificationStamp = (Double) mt2OldModificationStamp.get(workspaceFile);
+            if (oldModificationStamp != null && oldModificationStamp.doubleValue() == newModificationStamp.doubleValue()) {
+                tryOptimizedImport = true;
+            } else {
+                tryOptimizedImport = false;
+            }
+            mt2OldModificationStamp.put(workspaceFile, newModificationStamp);
+        } else {
+            tryOptimizedImport = true;
+        }
+        if (tryOptimizedImport) {
+            final Iterator it = oldImports.iterator();
+            while (it.hasNext()) {
+                final Object oldImportObject = it.next();
+                if (oldImportObject instanceof SpecificScript) {
+                    final SpecificScript oldImport = (SpecificScript) oldImportObject;
+                    if (oldImport.getFile().equals(file)) {
+                        oldImport.clearFoundProperties();
+                        oldImport.reset(new ArrayList(fileHierarchy));
+                        addImport(oldImport);
+                        oldImport.setSpecific(this);
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public void addImport(IEvalSettings element) {
+        super.addImport(element);
+    }
+
+    /**
+     * Quick imports : old script modification stamp.
+     */
+    private final Map mt2OldModificationStamp = new HashMap();
+
+    /**
+     * Quick imports : old imports.
+     */
+    private List oldImports = new ArrayList();
+
+    /**
+     * It checks the semantic of the links.
+     * 
+     * @param problems
+     *            are the semantic problems detected during this checking.
+     */
+    protected void checkAllExpressions(List problems) {
+
+        if (metamodel == null) {
+            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.InvalidImportSequence"), this, 0)); //$NON-NLS-1$
+        } else {
+            final Iterator textTemplates = this.textTemplates.entrySet().iterator();
+            while (textTemplates.hasNext()) {
+                final Map.Entry entry = (Map.Entry) textTemplates.next();
+                final String type = ((ScriptDescriptor) entry.getKey()).type;
+                final Template template = (Template) entry.getValue();
+                checkAllExpressions(problems, type, template);
+            }
+            final Iterator fileTemplates = this.fileTemplates.entrySet().iterator();
+            while (fileTemplates.hasNext()) {
+                final Map.Entry entry = (Map.Entry) fileTemplates.next();
+                final String type = (String) entry.getKey();
+                final Template template = (Template) entry.getValue();
+                checkAllExpressions(problems, type, template);
+            }
+        }
+
+    }
+
+    private void checkAllExpressions(List problems, String type, Template template) {
+        // Get the EClassifier for the identifier
+        final EClassifier classifier = ETools.getEClassifier(metamodel, type);
+        if (classifier == null) {
+            problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedClassifier", new Object[] { type, }), this, template.getPos())); //$NON-NLS-1$
+        } else {
+            // Check the elements of the template
+            final List allElements = template.getAllElements(TemplateCallSetExpression.class);
+            if (template.getPostExpression() != null) {
+                allElements.addAll(template.getPostExpression().getAllElements(TemplateCallSetExpression.class));
+            }
+            final Iterator elements = allElements.iterator();
+            while (elements.hasNext()) {
+                final TemplateCallSetExpression callSet = (TemplateCallSetExpression) elements.next();
+                if (callSet != null) {
+                    if (!callSet.isPredefined()) {
+                        // Check not predefined links
+                        Object resolvedType = callSet.getRootResolver(classifier, this);
+                        final Iterator calls = callSet.iterator();
+                        TemplateCallExpression call = null;
+                        while (resolvedType != null && calls.hasNext()) {
+                            // Remark : resolvedType == GENERIC_TYPE
+                            // => resolvedType != null
+                            call = (TemplateCallExpression) calls.next();
+                            if (resolvedType == IEvalSettings.GENERIC_TYPE && call.getLink().length() > 0) {
+                                final char[] array = call.getLink().toCharArray();
+                                for (int i = 0; i < array.length; i++) {
+                                    if (!Character.isJavaIdentifierPart(array[i])) {
+                                        problems.add(new TemplateSyntaxException(
+                                                AcceleoGenMessages.getString("TemplateSyntaxError.InvalidCharacter", new Object[] { Character.toString(array[i]), }), this, new Int2(call.getPos().b() + i, call.getPos().b() + i + 1))); //$NON-NLS-1$
+                                    }
+                                }
+                            }
+                            resolvedType = resolveType(resolvedType, call);
+                        }
+                        if (call != null) {
+                            if (resolvedType == null) {
+                                problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.UnresolvedCall", new Object[] { call, }), this, call.getPos())); //$NON-NLS-1$
+                            }
+                        }
+                    } else {
+                        // Check the user tags
+                        if (callSet.getFirst().getLink().equals(TemplateConstants.USER_BEGIN_NAME) && callSet.getFirst().countArguments() == 0) {
+                            // Remark : isPredefined() &&
+                            // USER_BEGIN_NAME => getParent() is
+                            // instance of TemplateFeatureStatement
+                            final TemplateFeatureStatement feature = (TemplateFeatureStatement) callSet.getParent();
+                            boolean valid = false;
+                            if (feature.getNext() != null && feature.getNext() instanceof TemplateText) {
+                                final String nextString = ((TemplateText) feature.getNext()).toString();
+                                final int iNewLine = nextString.indexOf("\n"); //$NON-NLS-1$
+                                if (iNewLine == -1 || nextString.substring(0, iNewLine).trim().length() > 0) {
+                                    valid = true;
+                                }
+                            }
+                            if (!valid && feature.getPrevious() != null && feature.getPrevious() instanceof TemplateText) {
+                                final String previousString = ((TemplateText) feature.getPrevious()).toString();
+                                final int iNewLine = previousString.lastIndexOf("\n"); //$NON-NLS-1$
+                                if (iNewLine == -1 || previousString.substring(iNewLine).trim().length() > 0) {
+                                    valid = true;
+                                }
+                            }
+                            if (!valid) {
+                                problems.add(new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.EmptyUserTag"), this, callSet.getPos())); //$NON-NLS-1$
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void newScript(ScriptDescriptor descriptor, String text, Int2 limitsTextTemplate) throws TemplateSyntaxException {
+        if (descriptor != null && text != null) {
+            limitsTextTemplate = Template.formatTemplate(text, limitsTextTemplate, 2);
+            final Template textTemplate = createTextTemplate(descriptor, text, limitsTextTemplate);
+            if (descriptor.getFileTemplate() != null) {
+                createFileTemplate(descriptor.getType(), text, descriptor.getFileTemplate(), textTemplate);
+            }
+            if (descriptor.getPostExpression() != null) {
+                final TemplateExpression postExpression = TemplateExpression.fromString(text, descriptor.getPostExpression(), this);
+                textTemplate.setPostExpression(postExpression);
+            }
+        }
+    }
+
+    /* (non-Javadoc) */
+    public boolean hasError(EObject object) {
+        return false;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode eGetTemplate(ENode node, String name, ENode[] args, LaunchManager mode) throws ENodeException, FactoryException {
+
+        return eGetTemplateSub(node, name, args, mode);
+    }
+
+    public ENode eGetTemplateSub(ENode node, String name, ENode[] args, LaunchManager mode) throws ENodeException, FactoryException {
+        if (textTemplateNames.contains(name)) {
+            if (node.isEObject()) {
+                try {
+                    final EObject object = node.getEObject();
+                    final Template template = getTextTemplateForEObject(object, name);
+                    if (template != null) {
+                        contextPush(IScript.TEMPLATE_ARGS, args);
+                        ENode result;
+                        try {
+                            final boolean withComment = !hasFileTemplate() && name.equals("write"); //$NON-NLS-1$
+                            if (withComment) {
+                                result = template.evaluateWithComment(object, mode);
+                            } else {
+                                result = template.evaluate(object, mode);
+                            }
+                            if (result.isNull()) {
+                                final List children = template.getSignificantStatements();
+                                if (children.size() > 1 || children.size() == 1 && !(children.get(0) instanceof TemplateFeatureStatement)) {
+                                    // isNull() => ""
+                                    result.asString();
+                                }
+                            }
+                            if (withComment && name.equals("write") && template.isEmptyEvaluation()) { //$NON-NLS-1$
+                                return null;
+                            }
+                        } finally {
+                            contextPop(IScript.TEMPLATE_ARGS);
+                        }
+                        return result;
+                    }
+                } catch (final ENodeCastException e) {
+                    // Never catch
+                }
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public Object resolveType(Object type, TemplateCallExpression call, int depth) {
+        if ("".equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_SCRIPT.equals(call.getPrefix())) { //$NON-NLS-1$
+            if (call.getLink().length() == 0) {
+                return IEvalSettings.GENERIC_TYPE;
+            }
+            if (type instanceof EClassifier) {
+                final Iterator textTemplates = this.textTemplates.entrySet().iterator();
+                while (textTemplates.hasNext()) {
+                    final Map.Entry entry = (Map.Entry) textTemplates.next();
+                    final ScriptDescriptor key = (ScriptDescriptor) entry.getKey();
+                    if (ETools.ofType((EClassifier) type, key.type) && key.name.equals(call.getLink())) {
+                        return IEvalSettings.GENERIC_TYPE;
+                    }
+                }
+            } else if (type == IEvalSettings.GENERIC_TYPE) {
+                final Iterator textTemplates = this.textTemplates.entrySet().iterator();
+                while (textTemplates.hasNext()) {
+                    final Map.Entry entry = (Map.Entry) textTemplates.next();
+                    final ScriptDescriptor key = (ScriptDescriptor) entry.getKey();
+                    if (key.name.equals(call.getLink())) {
+                        return IEvalSettings.GENERIC_TYPE;
+                    }
+                }
+            }
+        }
+        return super.resolveType(type, call, depth);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public Object[] getCompletionProposals(Object type, int depth) {
+        final List result = new ArrayList();
+        // Templates proposals
+        if (type instanceof EClassifier) {
+            final Iterator textTemplates = this.textTemplates.entrySet().iterator();
+            while (textTemplates.hasNext()) {
+                final Map.Entry entry = (Map.Entry) textTemplates.next();
+                if (ETools.ofType((EClassifier) type, ((ScriptDescriptor) entry.getKey()).type)) {
+                    result.add(entry);
+                }
+            }
+        }
+        // Other proposals
+        result.addAll(Arrays.asList(super.getCompletionProposals(type, depth)));
+        return result.toArray();
+    }
+
+    /**
+     * Clears the found properties.
+     */
+    private void clearFoundProperties() {
+        name2Properties.clear();
+        allProperties = null;
+    }
+
+    /**
+     * Gets the property for the key and the property file (without extension).
+     * 
+     * @param name
+     *            is the name of the property file (without ".properties"
+     *            extension)
+     * @param key
+     *            is the key
+     * @return the value for the given key
+     * @throws CoreException
+     * @throws IOException
+     */
+    public String getProperty(String name, String key) throws CoreException, IOException {
+        final Properties properties = getOrCreateProperties(name);
+        if (properties != null) {
+            return properties.getProperty(key);
+        } else {
+            return null;
+        }
+    }
+
+    private Properties getOrCreateProperties(String name) throws CoreException, IOException {
+        Properties properties = (Properties) name2Properties.get(name);
+        if (properties == null) {
+            boolean found = false;
+            final List containers = getPropertyContainers();
+            final Iterator it = containers.iterator();
+            while (it.hasNext() && !found) {
+                final File container = (File) it.next();
+                if (container.exists() && container.isDirectory()) {
+                    final File[] members = container.listFiles();
+                    for (int i = 0; i < members.length && !found; i++) {
+                        if (members[i].isFile() && (name + ".properties").equals(members[i].getName())) { //$NON-NLS-1$
+                            properties = new Properties();
+                            properties.load(members[i].toURL().openStream());
+                            name2Properties.put(name, properties);
+                            found = true;
+                        }
+                    }
+                }
+            }
+        }
+        return properties;
+    }
+
+    private final Map name2Properties = new HashMap();
+
+    /**
+     * Gets the value for the key in all the properties files.
+     * 
+     * @param key
+     *            is the key
+     * @return the value for the given key
+     * @throws CoreException
+     * @throws IOException
+     */
+    public String getProperty(String key) throws CoreException, IOException {
+        final Properties[] properties = getOrCreateProperties();
+        for (Properties propertie : properties) {
+            if (propertie != null) {
+                final String value = propertie.getProperty(key);
+                if (value != null) {
+                    return value;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Properties[] getOrCreateProperties() throws CoreException, IOException {
+        if (allProperties == null) {
+            final List allPropertiesList = new ArrayList();
+            final List containers = getPropertyContainers();
+            final Iterator it = containers.iterator();
+            while (it.hasNext()) {
+                final File container = (File) it.next();
+                if (container.exists() && container.isDirectory()) {
+                    final File[] members = container.listFiles();
+                    for (File member : members) {
+                        if (member.isFile() && member.getName() != null && member.getName().endsWith(".properties")) { //$NON-NLS-1$
+                            final Properties properties = new Properties();
+                            properties.load(member.toURL().openStream());
+                            name2Properties.put(new Path(member.getName()).removeFileExtension().lastSegment(), properties);
+                            allPropertiesList.add(properties);
+                        }
+                    }
+                }
+            }
+            allProperties = (Properties[]) allPropertiesList.toArray(new Properties[allPropertiesList.size()]);
+        }
+        return allProperties;
+    }
+
+    private Properties[] allProperties = null;
+
+    /**
+     * Gets the properties files containers.
+     * 
+     * @return the properties files containers
+     */
+    protected List getPropertyContainers() {
+        final List result = new ArrayList();
+        if (chainFile != null && chainFile.getParentFile() != null) {
+            result.add(chainFile.getParentFile());
+        }
+        if (file != null && file.getParentFile() != null) {
+            result.add(file.getParentFile());
+            File project = null;
+            final IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath()));
+            if (workspaceFile != null && workspaceFile.isAccessible()) {
+                project = workspaceFile.getProject().getLocation().toFile();
+            }
+            final String pluginId = AcceleoModuleProvider.getDefault().getPluginId(file);
+            if (pluginId != null) {
+                final Bundle bundle = Platform.getBundle(pluginId);
+                if (bundle != null) {
+                    final URL url = bundle.getEntry("/"); //$NON-NLS-1$
+                    if (url != null) {
+                        final File file = new File(Resources.transformToAbsolutePath(url));
+                        if (file.exists()) {
+                            project = file;
+                        }
+                    }
+                }
+            }
+            if (project != null && project.exists()) {
+                File parent = file.getParentFile().getParentFile();
+                while (parent != null && parent.exists()) {
+                    result.add(parent);
+                    if (parent.equals(project)) {
+                        break;
+                    } else {
+                        parent = parent.getParentFile();
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /* (non-Javadoc) */
+    public boolean validateCall(TemplateCallExpression call) {
+        return "".equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_SCRIPT.equals(call.getPrefix()); //$NON-NLS-1$
+    }
+
+    /**
+     * Sets initProfiling value.
+     * 
+     * @param initProfiling
+     */
+    public void setInitProfiling(boolean initProfiling) {
+        this.initProfiling = initProfiling;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/EvalJavaService.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/EvalJavaService.java
new file mode 100644
index 0000000..31ac993
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/EvalJavaService.java
@@ -0,0 +1,664 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.emf.ecore.EObject;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoEcoreGenPlugin;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateLiteralExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.AbstractScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IEvalSettings;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.ContextServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.ENodeServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.EObjectServices;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services.RequestServices;
+import org.eclipse.sirius.query.legacy.tools.classloaders.AcceleoClassLoader;
+import org.eclipse.sirius.query.legacy.tools.classloaders.AcceleoGenClassLoader;
+import org.eclipse.sirius.query.legacy.tools.plugins.AcceleoModuleProvider;
+
+/**
+ * Java services element that can be used during a code generation.
+ * 
+ * 
+ */
+public class EvalJavaService implements IEvalSettings {
+
+    private static String[] SERVICES_WITH_TYPE_RESOLVE = new String[] { "filter", "cast", "until", "eContainer", "eAllContents", "current" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+
+    private static String[] SERVICES_WITH_TYPE_BRIDGE = new String[] { "select", "delete", "sep", "nGet", "trace", "debug", "nFirst", "nLast", "sort", "nSort", "minimize", "nMinimize", "reverse", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$
+            "nReverse" }; //$NON-NLS-1$
+
+    private static List getTypeResolveList() {
+        if (EvalJavaService.typeResolveList == null) {
+            EvalJavaService.typeResolveList = new ArrayList();
+            for (String element : EvalJavaService.SERVICES_WITH_TYPE_RESOLVE) {
+                EvalJavaService.typeResolveList.add(element);
+            }
+        }
+        return EvalJavaService.typeResolveList;
+    }
+
+    private static List typeResolveList = null;
+
+    private static List getTypeBridgeList() {
+        if (EvalJavaService.typeBridgeList == null) {
+            EvalJavaService.typeBridgeList = new ArrayList();
+            for (String element : EvalJavaService.SERVICES_WITH_TYPE_BRIDGE) {
+                EvalJavaService.typeBridgeList.add(element);
+            }
+        }
+        return EvalJavaService.typeBridgeList;
+    }
+
+    private static List typeBridgeList = null;
+
+    /**
+     * The default evaluation mode.
+     */
+    public static final int MODE_DEFAULT = 0;
+
+    /**
+     * The 'ENode' evaluation mode : ENode services are available.
+     */
+    public static final int MODE_ENODE = 1;
+
+    /**
+     * The 'ENodeList' evaluation mode : ENodeList services are available.
+     */
+    public static final int MODE_LIST = 2;
+
+    /**
+     * The evaluation mode.
+     */
+    protected int mode = EvalJavaService.MODE_DEFAULT;
+
+    /**
+     * Instance that contains the services.
+     */
+    protected Object instance;
+
+    /**
+     * The class loader.
+     */
+    private ClassLoader loader = null;
+
+    /**
+     * Gets the service for the given name
+     */
+    private final Map name2service = new HashMap();
+
+    /**
+     * Indicates if the services have a script context.
+     */
+    private boolean hasScriptContext = true;
+
+    /**
+     * Constructor.
+     * 
+     * @param instance
+     *            is the instance that contains the services
+     * @param hasScriptContext
+     *            indicates if the services have a script context
+     */
+    public EvalJavaService(Object instance, boolean hasScriptContext) {
+        this.instance = instance;
+        this.hasScriptContext = hasScriptContext;
+        initializeName2service();
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script that imports the service
+     * @param className
+     *            is the class to be created
+     * @throws JavaServiceNotFoundException
+     */
+    public EvalJavaService(File script, String className) throws JavaServiceNotFoundException {
+        // Remark : script "fr.package.template" -> class "fr.package.Template"
+        String shortName = className;
+        String path = ""; //$NON-NLS-1$
+        final int jDot = className.lastIndexOf("."); //$NON-NLS-1$
+        if (jDot > -1) {
+            shortName = className.substring(jDot + 1);
+            path = className.substring(0, jDot);
+        }
+        if (shortName.length() > 0) {
+            shortName = shortName.substring(0, 1).toUpperCase() + shortName.substring(1);
+        }
+        className = (path.length() > 0 ? path + '.' : "") + shortName; //$NON-NLS-1$
+        initialize(script, className);
+        initializeName2service();
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script that imports the service
+     * @throws JavaServiceNotFoundException
+     */
+    public EvalJavaService(File script) throws JavaServiceNotFoundException {
+        // Remark : script "/fr/package/template.mt" -> class
+        // "fr.package.Template"
+        String name = new Path(script.getName()).removeFileExtension().lastSegment();
+        if (name.length() > 0) {
+            name = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+        }
+        final String[] segments = getPackagePath(script).append(name).segments();
+        // ASSERT (segments.length > 0){
+        // Java class name
+        final StringBuffer className = new StringBuffer();
+        className.append(segments[0]);
+        for (int i = 1; i < segments.length; i++) {
+            className.append('.');
+            className.append(segments[i]);
+        }
+        initialize(script, className.toString());
+        initializeName2service();
+    }
+
+    /**
+     * @return the evaluation mode
+     */
+    public int getMode() {
+        return mode;
+    }
+
+    /**
+     * @param mode
+     *            is the evaluation mode
+     */
+    public void setMode(int mode) {
+        this.mode = mode;
+    }
+
+    /**
+     * @return true if the services have a script context
+     */
+    public boolean hasScriptContext() {
+        return hasScriptContext;
+    }
+
+    /**
+     * @return the instance
+     */
+    public Object getInstance() {
+        return instance;
+    }
+
+    private void initialize(File script, String className) throws JavaServiceNotFoundException {
+        try {
+            loader = createClassLoader(script);
+            final Class c = loader.loadClass(className);
+            instance = c.newInstance();
+        } catch (final Exception e) {
+            throw new JavaServiceNotFoundException(AcceleoGenMessages.getString("EvalJavaService.UnresolvedService", new Object[] { e.getMessage(), })); //$NON-NLS-1$
+        }
+    }
+
+    private void initializeName2service() {
+        name2service.clear();
+        if (instance != null) {
+            final Method[] methods = instance.getClass().getMethods();
+            for (Method method : methods) {
+                if (method.getDeclaringClass() == instance.getClass() && method.getParameterTypes().length > 0) {
+                    final String key = method.getName() + method.getParameterTypes().length;
+                    final Method[] name2values = (Method[]) name2service.get(key);
+                    if (name2values == null) {
+                        name2service.put(key, new Method[] { method });
+                    } else {
+                        final List name2values_ = new ArrayList(name2values.length + 1);
+                        boolean ok = false;
+                        for (Method name2value : name2values) {
+                            if (name2value.getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0]) || name2value.getParameterTypes()[0] == ENode.class) {
+                                name2values_.add(method);
+                                ok = true;
+                            }
+                            name2values_.add(name2value);
+                        }
+                        if (!ok) {
+                            name2values_.add(method);
+                        }
+                        name2service.put(key, name2values_.toArray(new Method[name2values_.size()]));
+                    }
+                }
+            }
+        }
+    }
+
+    private Method[] getPotentialMethods(String name, int argsCount) {
+        final String key = name + argsCount;
+        return (Method[]) name2service.get(key);
+    }
+
+    /**
+     * Gets the package path of the given script
+     * 
+     * @param script
+     *            is the script
+     * @return the full path of the package
+     */
+    private IPath getPackagePath(File script) {
+        final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(script.getAbsolutePath()));
+        if (file != null && file.isAccessible()) {
+            return file.getProjectRelativePath().removeLastSegments(1).removeFirstSegments(1);
+        }
+        final String path = AcceleoModuleProvider.getDefault().getRelativePath(script);
+        if (path != null) {
+            return new Path(path).removeLastSegments(1);
+        } else {
+            return new Path(""); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Creates the default class loader for the given script.
+     * 
+     * @param script
+     *            is the script
+     * @return the default class loader
+     */
+    private ClassLoader createClassLoader(File script) {
+        final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(script.getAbsolutePath()));
+        if (file != null && file.isAccessible()) {
+            return new AcceleoGenClassLoader(file.getProject(), EvalJavaService.class.getClassLoader());
+        }
+        final String pluginId = AcceleoModuleProvider.getDefault().getPluginId(script);
+        if (pluginId != null) {
+            final Bundle bundle = Platform.getBundle(pluginId);
+            if (bundle != null) {
+                return new AcceleoGenClassLoader(bundle, EvalJavaService.class.getClassLoader());
+            }
+        }
+        return EvalJavaService.class.getClassLoader();
+    }
+
+    /* (non-Javadoc) */
+    public ENode eGet(TemplateCallExpression call, ENode node, ENode[] args, LaunchManager mode, boolean recursiveSearch) throws FactoryException, ENodeException {
+        if (name2service.containsKey(call.getLink() + (args.length + 1))) {
+            if (node.isEObject()) {
+                final ClassLoader old = AcceleoClassLoader.getPreferredClassLoader();
+                try {
+                    AcceleoClassLoader.setPreferredLoader(node.getEObject());
+                    return eGetSub(call, node, args, mode);
+                } catch (final ENodeCastException e) {
+                    // Never catch
+                    return null;
+                } finally {
+                    AcceleoClassLoader.setPreferredClassLoader(old);
+                }
+            } else {
+                return eGetSub(call, node, args, mode);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private ENode eGetSub(TemplateCallExpression call, ENode node, ENode[] args, LaunchManager runMode) throws FactoryException, ENodeException {
+        // ASSERT (instance != null){
+        // Get the type and the value for each argument
+        final List argTypesList = new ArrayList(args.length + 1);
+        final List argValuesList = new ArrayList(args.length + 1);
+        argTypesList.add(null);
+        argValuesList.add(null);
+        for (final ENode arg : args) {
+            argTypesList.add(arg.getTypeClass());
+            argValuesList.add(arg.getValue());
+        }
+        final Class[] argTypes = (Class[]) argTypesList.toArray(new Class[argTypesList.size()]);
+        final Object[] argValues = argValuesList.toArray();
+        // Get the method
+        Method m = null;
+        if (mode == EvalJavaService.MODE_DEFAULT && !node.isNull()) {
+            argTypes[0] = node.getTypeClass();
+            argValues[0] = node.getValue();
+            m = eGetMethod(call.getLink(), argTypes, argValues[0]);
+        } else if (mode == EvalJavaService.MODE_ENODE) {
+            argTypes[0] = ENode.class;
+            argValues[0] = node;
+            m = eGetMethod(call.getLink(), argTypes, argValues[0]);
+        } else if (mode == EvalJavaService.MODE_LIST && node.isList()) {
+            try {
+                argTypes[0] = ENodeList.class;
+                argValues[0] = node.getList();
+                m = eGetMethod(call.getLink(), argTypes, argValues[0]);
+            } catch (final ENodeCastException e1) {
+                m = null;
+            }
+            if (m == null) {
+                try {
+                    argTypes[0] = List.class;
+                    argValues[0] = node.getList().asList();
+                    m = eGetMethod(call.getLink(), argTypes, argValues[0]);
+                } catch (final ENodeCastException e2) {
+                    m = null;
+                }
+            }
+        }
+        if (m == null) {
+            // Try to adapt parameters
+            if (instance != null) {
+                final Method[] methods = getPotentialMethods(call.getLink(), argTypes.length);
+                if (methods != null) {
+                    for (int i = 0; m == null && i < methods.length; i++) {
+                        boolean ok = true;
+                        final Class[] parameterTypes = methods[i].getParameterTypes();
+                        if (parameterTypes.length > 0) {
+                            if (mode == EvalJavaService.MODE_DEFAULT) {
+                                final Class parameterType = ENode.getAdapterType(parameterTypes[0]);
+                                if (parameterType != null) {
+                                    argTypes[0] = parameterType;
+                                    try {
+                                        argValues[0] = node.getAdapterValue(parameterType);
+                                    } catch (final ENodeCastException e) {
+                                        ok = false;
+                                    }
+                                } else {
+                                    ok = false;
+                                }
+                            }
+                            if (mode == EvalJavaService.MODE_DEFAULT && ok || mode == EvalJavaService.MODE_ENODE && parameterTypes[0] == ENode.class || mode == EvalJavaService.MODE_LIST
+                                    && parameterTypes[0] == ENodeList.class) {
+                                for (int j = 1; j < parameterTypes.length; j++) {
+                                    final Class parameterType = ENode.getAdapterType(parameterTypes[j]);
+                                    if (parameterType != null) {
+                                        argTypes[j] = parameterType;
+                                        try {
+                                            argValues[j] = args[j - 1].getAdapterValue(parameterType);
+                                        } catch (final ENodeCastException e) {
+                                            ok = false;
+                                            break;
+                                        }
+                                    } else {
+                                        ok = false;
+                                        break;
+                                    }
+                                }
+                                if (ok) {
+                                    m = methods[i];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (m != null) {
+            // Display method
+            String displayString = m.getName() + " ("; //$NON-NLS-1$
+            final Class[] paramTypes = m.getParameterTypes();
+            for (int j = 1; j < paramTypes.length; j++) { // The first
+                // parameter is
+                // ignored
+                final Class paramType = paramTypes[j];
+                displayString += EvalJavaService.getSimpleName(paramType);
+                if (j + 1 < paramTypes.length) {
+                    displayString += ", "; //$NON-NLS-1$
+                }
+            }
+            displayString += ')';
+            if (m.getReturnType() != null) {
+                displayString += ' ' + EvalJavaService.getSimpleName(m.getReturnType());
+            }
+            displayString += " - " + EvalJavaService.getSimpleName(m.getDeclaringClass()); //$NON-NLS-1$
+            // Invoke method on instance
+            Object result;
+            try {
+                if (call.getLink().equals("select") && call.getScript() instanceof AbstractScript && call.countArguments() > 0) { //$NON-NLS-1$
+                    ((AbstractScript) call.getScript()).contextPush(IScript.ARGUMENT_POSITION, call.getFirstArgument().getPos());
+                }
+                try {
+                    // void => ""
+                    if (m.getReturnType() != null && "void".equals(EvalJavaService.getSimpleName(m.getReturnType()))) { //$NON-NLS-1$
+                        m.invoke(instance, argValues);
+                        result = ""; //$NON-NLS-1$
+                    } else {
+                        result = m.invoke(instance, argValues);
+                    }
+                } catch (final Exception npe) {
+                    if (mode == EvalJavaService.MODE_DEFAULT && argValues.length > 0 && argValues[0] == null) {
+                        result = null;
+                    } else {
+                        throw npe;
+                    }
+                } finally {
+                    if (call.getLink().equals("select") && call.getScript() instanceof AbstractScript && call.countArguments() > 0) { //$NON-NLS-1$
+                        ((AbstractScript) call.getScript()).contextPop(IScript.ARGUMENT_POSITION);
+                    }
+                }
+            } catch (final InvocationTargetException e) {
+                if (e.getTargetException() instanceof FactoryException) {
+                    throw (FactoryException) e.getTargetException();
+                } else if (e.getTargetException() instanceof ENodeException) {
+                    throw (ENodeException) e.getTargetException();
+                } else {
+                    final StringBuffer errorMessage = new StringBuffer("\n"); //$NON-NLS-1$
+                    errorMessage.append((e.getTargetException() != null ? e.getTargetException().getClass().getName() + " : " + e.getTargetException().getMessage() : "")); //$NON-NLS-1$ //$NON-NLS-2$
+                    throw new ENodeException(
+                            AcceleoGenMessages.getString("EvalJavaService.RuntimeException", new Object[] { displayString, errorMessage.toString(), }), call.getPos(), call.getScript(), //$NON-NLS-1$
+                            node, true, e.getTargetException());
+                }
+            } catch (final Exception e) {
+                final StringBuffer errorMessage = new StringBuffer("\n"); //$NON-NLS-1$
+                errorMessage.append(e.getClass().getName());
+                errorMessage.append(" : "); //$NON-NLS-1$
+                errorMessage.append(e.getMessage());
+                throw new ENodeException(
+                        AcceleoGenMessages.getString("EvalJavaService.RuntimeException", new Object[] { displayString, errorMessage.toString(), }), call.getPos(), call.getScript(), node, true, //$NON-NLS-1$
+                        e);
+            }
+            final ENode createTry = ENode.createTry(result, node);
+            if (createTry != null) {
+                return createTry;
+            } else {
+                throw new ENodeException(
+                        AcceleoGenMessages.getString("EvalJavaService.RuntimeType", new Object[] { displayString, result.getClass().getName(), }), call.getPos(), call.getScript(), node, true); //$NON-NLS-1$
+            }
+        } else {
+            // Service doesn't exist
+            return null;
+        }
+    }
+
+    /**
+     * Gets the simple name of the given class.
+     * <p>
+     * Sample : return 'Object' for 'java.lang.Object'
+     * 
+     * @param c
+     *            is the class
+     * @return the name
+     */
+    public static String getSimpleName(Class c) {
+        String name = c.getName();
+        final int i = name.lastIndexOf("."); //$NON-NLS-1$
+        if (i > -1) {
+            name = name.substring(i + 1);
+        }
+        return name;
+    }
+
+    /**
+     * Defines if the method belongs to an external service.
+     * 
+     * @param m
+     *            the method
+     * @return boolean
+     */
+    public static boolean isExternalService(Method m) {
+        boolean isExternal = false;
+
+        Class[] interfaces = m.getDeclaringClass().getInterfaces();
+
+        if (interfaces != null) {
+            for (Class interface1 : interfaces) {
+                isExternal = isExternal || EvalJavaService.getSimpleName(interface1).equals("IExternalJavaService"); //$NON-NLS-1$
+            }
+        }
+        return isExternal;
+    }
+
+    /**
+     * Defines if the method is deprecated.
+     * 
+     * @param m0
+     *            the method
+     * @return boolean
+     */
+    public static boolean isDeprecatedService(Method m0) {
+        boolean isDeprecated = false;
+
+        try {
+            final Method m2 = m0.getDeclaringClass().getDeclaredMethod("getDeprecatedMethods", null); //$NON-NLS-1$
+            if (m2 != null) {
+                final Object methods = m2.invoke(m0.getDeclaringClass().newInstance(), null);
+                if (methods != null && methods instanceof Method[]) {
+                    final Method[] mts = (Method[]) methods;
+                    for (final Method m1 : mts) {
+                        isDeprecated = isDeprecated || ((m0.getName() + m0.toString()).equals(m1.getName() + m1.toString()));
+                    }
+                }
+            }
+        } catch (Exception e) {
+            AcceleoEcoreGenPlugin.getDefault().log(e.getMessage(), true);
+        }
+        return isDeprecated;
+    }
+
+    private Method eGetMethod(String name, Class[] argTypes, Object receiver) {
+        final Method[] methods = getPotentialMethods(name, argTypes.length);
+        if (methods != null) {
+            for (Method method : methods) {
+                final Class[] parameterTypes = method.getParameterTypes();
+                // ASSERT parameterTypes.length > 0
+                if (argTypes[0] != EObject.class || parameterTypes[0].isInstance(receiver)) {
+                    boolean ok = true;
+                    for (int j = 0; j < parameterTypes.length; j++) {
+                        if (argTypes[j] == EObject.class && !argTypes[j].isAssignableFrom(parameterTypes[j]) || argTypes[j] != EObject.class && argTypes[j] != parameterTypes[j]) {
+                            ok = false;
+                            break;
+                        }
+                    }
+                    if (ok) {
+                        return method;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc) */
+    public Object resolveType(Object type, TemplateCallExpression call, int depth) {
+        if (instance != null && type != null) { // Remark : type == GENERIC_TYPE
+            // => type != null
+            final List quickKey = new ArrayList();
+            quickKey.add(type);
+            quickKey.add(call.toString()); // not getLink() because arguments
+            if (quickResolveType.containsKey(quickKey)) {
+                return quickResolveType.get(quickKey);
+            } else {
+                Object resolvedType = null;
+                // 'filter' case
+                if (instance instanceof ENodeServices || instance instanceof EObjectServices) {
+                    if (EvalJavaService.getTypeResolveList().contains(call.getLink()) && call.countArguments() > 0) {
+                        final TemplateExpression firstArg = call.getFirstArgument();
+                        if (firstArg instanceof TemplateLiteralExpression) {
+                            final Object result = ((TemplateLiteralExpression) firstArg).resolveAsEClassifier();
+                            if (result != null) {
+                                resolvedType = result;
+                            }
+                        }
+                    }
+                }
+                if (resolvedType == null && (instance instanceof RequestServices || instance instanceof ENodeServices || instance instanceof ContextServices)) {
+                    if (EvalJavaService.getTypeBridgeList().contains(call.getLink())) {
+                        resolvedType = type;
+                    }
+                }
+                // Use declared methods
+                if (resolvedType == null) {
+                    final Method[] methods = getPotentialMethods(call.getLink(), call.countArguments() + 1);
+                    if (methods != null && methods.length > 0 && methods[0].getDeclaringClass() == instance.getClass()) {
+                        resolvedType = IEvalSettings.GENERIC_TYPE;
+                    }
+                }
+                quickResolveType.put(quickKey, resolvedType);
+                return resolvedType;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private final Map quickResolveType = new HashMap();
+
+    /* (non-Javadoc) */
+    public Object[] getCompletionProposals(Object type, int depth) {
+        if (instance != null) {
+            final Collection result = new TreeSet(new Comparator() {
+                public int compare(Object arg0, Object arg1) {
+                    Method m0 = (Method) arg0;
+                    Method m1 = (Method) arg1;
+                    return (m0.getName() + m0.toString()).compareTo(m1.getName() + m1.toString());
+                }
+            });
+            final Method[] methods = instance.getClass().getMethods();
+            for (final Method method : methods) {
+                if (method.getDeclaringClass() == instance.getClass() && method.getParameterTypes().length >= 1) {
+                    result.add(method);
+                }
+            }
+            return result.toArray();
+        } else {
+            return new Object[] {};
+        }
+    }
+
+    /* (non-Javadoc) */
+    public boolean validateCall(TemplateCallExpression call) {
+        return "".equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_JAVA.equals(call.getPrefix()); //$NON-NLS-1$
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/EvalModel.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/EvalModel.java
new file mode 100644
index 0000000..ac02096
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/EvalModel.java
@@ -0,0 +1,341 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EOperation;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EParameter;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.EFactory;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalFailure;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateCallExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IEvalSettings;
+
+/**
+ * Metamodel element that can be used during a code generation.
+ * 
+ * 
+ */
+public class EvalModel implements IEvalSettings {
+
+    /**
+     * URI of the metamodel.
+     */
+    protected String uri;
+
+    /**
+     * Root element of the metamodel.
+     */
+    protected EPackage metamodel;
+
+    /**
+     * Indicates if the errors are shown.
+     */
+    private final boolean logErrors;
+
+    /**
+     * Constructor.
+     * 
+     * @param uri
+     *            is the URI of the metamodel
+     */
+    public EvalModel(String uri) {
+        this(uri, true);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param uri
+     *            is the URI of the metamodel
+     * @param logErrors
+     *            indicates if the errors are shown
+     */
+    public EvalModel(String uri, boolean logErrors) {
+        this.uri = uri;
+        this.logErrors = logErrors;
+        this.metamodel = ETools.uri2EPackage(uri, false);
+    }
+
+    /**
+     * @return the URI of the metamodel
+     */
+    public String getUri() {
+        return uri;
+    }
+
+    /**
+     * @return the root element of the metamodel
+     */
+    public EPackage getMetamodel() {
+        return metamodel;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ENode eGet(TemplateCallExpression call, ENode node, ENode[] args, LaunchManager mode, boolean recursiveSearch) throws FactoryException, ENodeException {
+        if (args.length == 0) {
+            return eGetSub(call, node, args, mode);
+        } else {
+            return null;
+        }
+    }
+
+    private ENode eGetSub(TemplateCallExpression call, ENode node, ENode[] args, LaunchManager mode) throws FactoryException, ENodeException {
+        EObject eObject = null;
+        if (node.isEObject()) {
+            try {
+                eObject = node.getEObject();
+                node = new ENode(eObject, call, mode.isSynchronize()); // for
+                // text
+                // to model
+            } catch (final ENodeCastException e) {
+                eObject = null;
+            }
+        }
+        ENode eval;
+        if (eObject != null && EFactory.eValid(eObject, call.getLink()) && call.countArguments() == 0) {
+            boolean hasMetaPrefix = TemplateConstants.LINK_PREFIX_METAMODEL.equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_METAMODEL_SHORT.equals(call.getPrefix());
+            final Object object = EFactory.eGet(eObject, call.getLink(), !hasMetaPrefix);
+            eval = eGetHolder(object, node);
+            final EStructuralFeature feature = eObject.eClass().getEStructuralFeature(call.getLink());
+            if (feature != null) {
+                final boolean containment = feature == null || !(feature instanceof EReference) || ((EReference) feature).isContainment();
+                eval.setContainment(containment);
+                final boolean optional = feature != null && feature instanceof EReference && ((EReference) feature).getLowerBound() == 0;
+                eval.setOptional(optional);
+            } else {
+                // nt templateCallExpression called is an eoperation
+                // with no parameter, this step is skipped
+            }
+        } else {
+            eval = null;
+        }
+        boolean isNaming;
+        try {
+            isNaming = call.getNextCall() != null && call.getNextCall().getLink().equals("naming") && call.countArguments() == 0 && call.getNextCall().countArguments() == 0 && node.isEObject() //$NON-NLS-1$
+                    && (eval == null || eval.isNull() || eval.isEObject() && eval.getEObject().eContainer() == null);
+        } catch (final ENodeCastException e1) {
+            isNaming = false;
+        }
+        if (isNaming) {
+            try {
+                // Sample : 'link.naming' is empty => try 'linkValue'
+                final String otherLink = call.getLink() + "Value"; //$NON-NLS-1$
+                String result;
+                result = EFactory.eGetAsString(eObject, otherLink);
+                if (result != null) {
+                    final ENode otherEval = new ENode(result, node);
+                    if (logErrors) {
+                        otherEval.log().addError(
+                                new EvalFailure(AcceleoGenMessages.getString("EvalModel.EvaluationEmptyNaming", new Object[] { otherLink, node.getEObject().eClass().getName(), call.getLink(), }))); //$NON-NLS-1$
+                    }
+                    call.getNextCall().ignoreNextEval();
+                    return otherEval;
+                }
+            } catch (final ENodeCastException e) {
+                // Never catch
+            } catch (final FactoryException e) {
+                // Never catch
+            }
+        }
+        return eval;
+    }
+
+    private ENode eGetHolder(Object object, ENode node) throws ENodeException {
+        ENode result = ENode.createTry(object, node);
+        if (result == null) {
+            result = new ENode(ENode.EMPTY, node);
+        }
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object resolveType(Object type, TemplateCallExpression call, int depth) {
+        if (type != null) {
+            // Remark : type == GENERIC_TYPE => type != null
+            if (type instanceof EClass) {
+                Object result = null;
+                if (call.countArguments() == 0) {
+                    result = checkingForFeature((EClass) type, call.getLink());
+                    if (result == null) {
+                        result = checkingForOperation((EClass) type, call.getLink(), call.countArguments());
+                    }
+                } else {
+                    result = checkingForOperation((EClass) type, call.getLink(), call.countArguments());
+                }
+                return result;
+            } else if (type == IEvalSettings.GENERIC_TYPE) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 
+     * @param eClass
+     *            EClass where the feature should be
+     * @param link
+     *            name of the feature
+     * @return type of the feature or null
+     */
+    private Object checkingForFeature(EClass eClass, String link) {
+        final EStructuralFeature feature = eClass.getEStructuralFeature(link);
+        if (feature != null) {
+            final EClassifier result = feature.getEType();
+            if (!"http://www.eclipse.org/emf/2002/Ecore".equals(uri) && result == EcorePackage.eINSTANCE.getEObject()) { //$NON-NLS-1$
+                return IEvalSettings.GENERIC_TYPE;
+            } else {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 
+     * @param eClass
+     *            EClass where the operation should be
+     * @param link
+     *            name of the feature
+     * @param argCount
+     * @return type of the feature or null
+     */
+    private Object checkingForOperation(EClass eClass, String link, int argCount) {
+        EOperation operation = null;
+        final Iterator it = eClass.getEAllOperations().iterator();
+        while (it.hasNext()) {
+            final EOperation currentOp = (EOperation) it.next();
+            if (currentOp.getName().equals(link) && currentOp.getEParameters().size() == argCount) {
+                operation = currentOp;
+                break;
+            }
+        }
+        if (operation != null) {
+            final EClassifier result = operation.getEType();
+            // !"http://www.eclipse.org/emf/2002/Ecore".equals(uri) &&
+            if (result == EcorePackage.eINSTANCE.getEObject()) {
+                return IEvalSettings.GENERIC_TYPE;
+            } else {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object[] getCompletionProposals(Object type, int depth) {
+        final Collection result = new ArrayList();
+        if (type != null && type instanceof EClass) {
+            result.addAll(getStructuralFeaturesProposals((EClass) type));
+            result.addAll(getOperationProposals((EClass) type));
+            return result.toArray();
+        } else {
+            return new Object[] {};
+        }
+    }
+
+    /**
+     * pre : eClass must be set
+     * 
+     * @param eClass
+     *            the EClass from witch we want the completion proposals
+     * @return all structural features of eClass ordered by name
+     */
+    private Collection getStructuralFeaturesProposals(EClass eClass) {
+        final Collection result = new TreeSet(new Comparator() {
+            public int compare(Object arg0, Object arg1) {
+                EStructuralFeature f0 = (EStructuralFeature) arg0;
+                EStructuralFeature f1 = (EStructuralFeature) arg1;
+                return f0.getName().compareTo(f1.getName());
+            }
+        });
+        result.addAll(eClass.getEAllStructuralFeatures());
+
+        return result;
+    }
+
+    /**
+     * pre : eClass must be set
+     * 
+     * @param eClass
+     *            the EClass from witch we want the completion proposals
+     * @return all operations of eClass ordered by name
+     */
+    private Collection getOperationProposals(EClass eClass) {
+        final Collection result = new TreeSet(new Comparator() {
+            public int compare(Object arg0, Object arg1) {
+                EOperation o0 = (EOperation) arg0;
+                EOperation o1 = (EOperation) arg1;
+                String o0tag = o0.getName();
+                String o1tag = o1.getName();
+                Iterator it = o0.getEParameters().iterator();
+                while (it.hasNext()) {
+                    o0tag += ((EParameter) it.next()).getEType().getName();
+                }
+                it = o1.getEParameters().iterator();
+                while (it.hasNext()) {
+                    o1tag += ((EParameter) it.next()).getEType().getName();
+                }
+
+                return o0tag.compareTo(o1tag);
+            }
+        });
+
+        final Iterator op = eClass.getEAllOperations().iterator();
+
+        while (op.hasNext()) {
+            final EOperation operation = (EOperation) op.next();
+            // filter to keep only EOperation without arguments and with a
+            // usable return type that is not declared by EObject
+            if (operation.getEType() != null && ENode.getAdapterType(operation.getEType().getClass()) != null && operation.getEParameters().size() == 0
+                    && !"EObject".equals(operation.getEContainingClass().getName())) {
+                result.add(operation);
+            }
+        }
+
+        return result;
+    }
+
+    /* (non-Javadoc) */
+    public boolean validateCall(TemplateCallExpression call) {
+        return "".equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_METAMODEL.equals(call.getPrefix()) || TemplateConstants.LINK_PREFIX_METAMODEL_SHORT.equals(call.getPrefix()); //$NON-NLS-1$
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/JavaServiceNotFoundException.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/JavaServiceNotFoundException.java
new file mode 100644
index 0000000..606b070
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/JavaServiceNotFoundException.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports;
+
+import org.eclipse.sirius.query.legacy.tools.log.AcceleoException;
+
+/**
+ * Java service not found.
+ * 
+ * 
+ */
+public class JavaServiceNotFoundException extends AcceleoException {
+
+    private static final long serialVersionUID = 1;
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     */
+    public JavaServiceNotFoundException(String message) {
+        super(message);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getMessage() {
+        return super.getMessage();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ContextServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ContextServices.java
new file mode 100644
index 0000000..a7f831a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ContextServices.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+
+/**
+ * System services for ENode elements.
+ * 
+ * 
+ */
+public class ContextServices {
+
+    /**
+     * Constructor.
+     */
+    public ContextServices() {
+    }
+
+    /**
+     * Puts the current node in the context for the given key, and return an
+     * empty string.
+     * 
+     * @param node
+     *            is the current node
+     * @param key
+     *            is the key in the context
+     * @deprecated
+     */
+    @Deprecated
+    public void nPut(ENode node, String key) {
+        put(node, key);
+    }
+
+    /**
+     * Puts the current node in the context for the given key, and return an
+     * empty string.
+     * 
+     * @param node
+     *            is the current node
+     * @param key
+     *            is the key in the context
+     */
+    public void put(ENode node, String key) {
+        context.put(key, node);
+    }
+
+    /**
+     * Gets the node for the given key in the context.
+     * 
+     * @param node
+     *            is the current node
+     * @param key
+     *            is the key in the context
+     * @return the node of the context
+     * @deprecated
+     */
+    @Deprecated
+    public ENode nGet(ENode node, ENode key) throws ENodeCastException, FactoryException {
+        if (key.isInt()) {
+            if (node.isList()) {
+                ENodeList list = node.getList();
+                ENode result = list.get(key.getInt());
+                if (result != null) {
+                    return result;
+                } else {
+                    return new ENode(ENode.EMPTY, node);
+                }
+            } else if (key.getInt() == 0) {
+                return node;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else if (key.isString()) {
+            // deprecated nGet(ENode node, String key)
+            return get(node, key.getString());
+        } else {
+            // deprecated nGet(ENode node, String key)
+            return get(node, (String) key.getAdapterValue(String.class));
+        }
+    }
+
+    /**
+     * Gets the node for the given key in the context.
+     * 
+     * @param node
+     *            is the current node
+     * @param key
+     *            is the key in the context
+     * @return the node of the context
+     */
+    public ENode get(ENode node, String key) {
+        ENode result = (ENode) context.get(key);
+        if (result != null) {
+            return result.copy();
+        } else {
+            return new ENode(ENode.EMPTY, node);
+        }
+    }
+
+    private Map context = new HashMap();
+
+    /**
+     * Pushes the current node into the context, and returns an empty string.
+     * 
+     * @param node
+     *            is the current node
+     * @deprecated
+     */
+    @Deprecated
+    public void nPush(ENode node) {
+        push(node);
+    }
+
+    /**
+     * Pushes the current node into the context, and returns an empty string.
+     * 
+     * @param node
+     *            is the current node
+     */
+    public void push(ENode node) {
+        stack.push(node);
+    }
+
+    /**
+     * Pops the context, and returns an empty string.
+     * 
+     * @param node
+     *            is the current node
+     * @deprecated
+     */
+    @Deprecated
+    public void nPop(ENode node) {
+        pop(node);
+    }
+
+    /**
+     * Pops the context, and returns an empty string.
+     * 
+     * @param node
+     *            is the current node
+     */
+    public void pop(ENode node) {
+        stack.pop();
+    }
+
+    /**
+     * Return the last node pushed into the context, and returns an empty
+     * string.
+     * 
+     * @param node
+     *            is the current node
+     * @return an empty string
+     * @deprecated
+     */
+    @Deprecated
+    public ENode nPeek(ENode node) {
+        return peek(node);
+    }
+
+    /**
+     * Return the last node pushed into the context, and returns an empty
+     * string.
+     * 
+     * @param node
+     *            is the current node
+     * @return an empty string
+     */
+    public ENode peek(ENode node) {
+        if (!stack.isEmpty()) {
+            return ((ENode) stack.peek()).copy();
+        } else {
+            return new ENode("", node); //$NON-NLS-1$
+        }
+    }
+
+    private Stack stack = new Stack();
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ENodeServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ENodeServices.java
new file mode 100644
index 0000000..7a59317
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ENodeServices.java
@@ -0,0 +1,771 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.EFactory;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.format.Conventions;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * System services for ENode elements.
+ * 
+ * 
+ */
+public class ENodeServices {
+
+    /**
+     * The script.
+     */
+    protected IScript script;
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public ENodeServices(IScript script) {
+        this.script = script;
+    }
+
+    /**
+     * Gets all the nodes whose type is the given type.
+     * <p>
+     * An element is kept only if it's an EObject whose type is the given type
+     * or if it isn't an EObject.
+     * <p>
+     * Sample :
+     * <p>
+     * <li>a is an instance of class A</li>
+     * <li>b is an instance of class B</li>
+     * <li>c is an instance of class C</li>
+     * <li>B extends A</li>
+     * <p>
+     * If type equals "A" and node is a list {a, "\n", b, c}
+     * <p>
+     * the result is a list {a, "\n", b}.
+     * 
+     * @param node
+     *            is the list
+     * @param type
+     *            is the type kept
+     * @return a list that contains the nodes whose type is the given type.
+     * @throws ENodeCastException
+     *             if the given node isn't a list
+     * @throws FactoryException
+     */
+    public ENode filter(ENode node, String type) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList res = new ENodeList();
+            ENodeIterator it = node.getList().iterator();
+            while (it.hasNext()) {
+                ENode child = filter(it.next(), type);
+                if (!child.isNull()) {
+                    res.add(child);
+                }
+            }
+            return new ENode(res, node);
+        } else if (node.isEObject()) {
+            if (EFactory.eInstanceOf(node.getEObject(), type)) {
+                return node;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Gets all the nodes whose type is the given type.
+     * <p>
+     * An element is kept only if it's an EObject whose type is the given type
+     * or if it isn't an EObject.
+     * <p>
+     * Sample :
+     * <p>
+     * <li>a is an instance of class A</li>
+     * <li>b is an instance of class B</li>
+     * <li>c is an instance of class C</li>
+     * <li>B extends A</li>
+     * <p>
+     * If type equals "A" and node is a list {a, "\n", b, c}
+     * <p>
+     * the result is a list {a, "\n", b}.
+     * 
+     * @param node
+     *            is the list
+     * @param type
+     *            is the type kept
+     * @return a list that contains the nodes whose type is the given type.
+     * @throws ENodeCastException
+     *             if the given node isn't a list
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode cast(ENode node, String type) throws ENodeCastException, FactoryException {
+        return filter(node, type);
+    }
+
+    /**
+     * Add a separator between each element of the list. It returns the given
+     * node if it isn't a list.
+     * <p>
+     * Sample :
+     * <p>
+     * If separator equals "\t" and node is a list {a, b, c} the result is a
+     * list {a, "\t", b, "\t", c}.
+     * 
+     * @param node
+     *            is the list
+     * @param separator
+     *            is the separator
+     * @return a list that contains a separator between each element.
+     * @throws FactoryException
+     */
+    public ENode sep(ENode node, String separator) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENodeList res = new ENodeList();
+            ENodeIterator it = list.iterator();
+            if (it.hasNext()) {
+                ENode element = it.next();
+                boolean needSeparator = element.size() > 0;
+                res.add(element);
+                while (it.hasNext()) {
+                    element = it.next();
+                    if (needSeparator && element.size() > 0) {
+                        res.add(new ENode(separator, node));
+                        needSeparator = true;
+                    } else if (!needSeparator) {
+                        needSeparator = element.size() > 0;
+                    }
+                    res.add(element);
+                }
+            }
+            return new ENode(res, node);
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Add a separator between each element of the list and serialize the list.
+     * It returns node.toString() if it isn't a list.
+     * <p>
+     * Sample :
+     * <p>
+     * If separator equals "\t" and node is a list {a, b, c} the result is a
+     * string : a + "\t" + b + "\t" + c.
+     * 
+     * @param node
+     *            is the list
+     * @param separator
+     *            is the separator
+     * @return a string that contains a separator between each element.
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode sepStr(ENode node, String separator) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENodeList res = new ENodeList();
+            ENodeIterator it = list.iterator();
+            if (it.hasNext()) {
+                ENode element = it.next();
+                boolean needSeparator = element.size() > 0;
+                res.add(element);
+                while (it.hasNext()) {
+                    element = it.next();
+                    if (needSeparator && element.size() > 0) {
+                        res.add(new ENode(separator, node));
+                        needSeparator = true;
+                    } else if (!needSeparator) {
+                        needSeparator = element.size() > 0;
+                    }
+                    res.add(element);
+                }
+            }
+            ENode result = new ENode(res, node);
+            result.asString();
+            return result;
+        } else {
+            node.asString();
+            return node;
+        }
+    }
+
+    /**
+     * Get recursively the feature value of an object. The recursivity is
+     * stopped when an element of the given type is found.
+     * <p>
+     * The given node must be an EObject.
+     * <p>
+     * Sample :
+     * <p>
+     * <li>a is an instance of class A</li>
+     * <li>b is an instance of class B</li>
+     * <li>c is an instance of class C</li>
+     * <li>a contains b</li>
+     * <li>b contains c</li>
+     * <li>'container' feature is defined on a, b, and c</li>
+     * <li>c.container returns b</li>
+     * <li>b.container returns a</li>
+     * <li>a.container returns null</li>
+     * <p>
+     * until(c,"container","A") returns a
+     * <p>
+     * until(b,"container","A") returns a
+     * <p>
+     * until(a,"container","A") returns a
+     * <p>
+     * until(b,"container","C") returns null
+     * <p>
+     * 
+     * @param node
+     *            is an EObject
+     * @param link
+     *            is the feature name
+     * @param type
+     *            is the type which stops the recursivity
+     * @return the found object or null
+     * @throws ENodeCastException
+     *             if the given node isn't an EObject
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode until(ENode node, String link, String type) throws ENodeCastException, FactoryException {
+        EObject object = node.getEObject();
+        while (object != null) {
+            if (EFactory.eInstanceOf(object, type)) {
+                return new ENode(object, node);
+            } else {
+                object = EFactory.eGetAsEObject(object, link);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the current node
+     */
+    public ENode current(ENode node) {
+        return node;
+    }
+
+    /**
+     * Returns the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @param level
+     *            is the level in the parent hierarchy
+     * @return the current node
+     * @throws ENodeCastException
+     */
+    public ENode current(ENode node, ENode arg) throws ENodeCastException {
+        if (arg.isString()) {
+            String type = arg.getString();
+            int i = 0;
+            Object value = script.contextAt(IScript.TEMPLATE_NODE, i);
+            while (value != null) {
+                ENode current = ENode.createTry(value, node);
+                if (current != null && current.isEObject()) {
+                    if (EFactory.eInstanceOf(current.getEObject(), type)) {
+                        return current;
+                    }
+                }
+                i++;
+                value = script.contextAt(IScript.TEMPLATE_NODE, i);
+            }
+        } else if (arg.isInt()) {
+            Object value = script.contextAt(IScript.TEMPLATE_NODE, arg.getInt());
+            return ENode.createTry(value, node);
+        }
+        return new ENode(ENode.EMPTY, node);
+    }
+
+    /**
+     * Transforms the node into a string.
+     * 
+     * @param node
+     *            is the current node
+     * @return the string node
+     */
+    public ENode toString(ENode node) {
+        node.asString();
+        return node;
+    }
+
+    /**
+     * Returns the adaptive value for the given type short name.
+     * 
+     * @param node
+     *            is the node
+     * @param type
+     *            is the type name : "EObject", "ENodeList", "String",
+     *            "boolean", "int", "double", "List", "ENode"
+     * @return the adaptive value
+     * @throws ENodeCastException
+     */
+    public ENode adapt(ENode node, String type) throws ENodeCastException {
+        Class c;
+        if ("EObject".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = EObject.class;
+        } else if ("ENodeList".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = ENodeList.class;
+        } else if ("String".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = String.class;
+        } else if ("boolean".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = boolean.class;
+        } else if ("int".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = int.class;
+        } else if ("double".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = double.class;
+        } else if ("List".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = List.class;
+        } else if ("ENode".equalsIgnoreCase(type)) { //$NON-NLS-1$
+            c = ENode.class;
+        } else {
+            c = null;
+        }
+        ENode result = ENode.createTry(node.getAdapterValue(c), node);
+        if (result != null) {
+            return result;
+        } else {
+            return new ENode(ENode.EMPTY, node);
+        }
+    }
+
+    /**
+     * It prints current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the current node
+     */
+    public ENode debug(ENode node) {
+        return trace(node);
+    }
+
+    /**
+     * It prints current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the current node
+     */
+    public ENode trace(ENode node) {
+        return trace(node, ""); //$NON-NLS-1$
+    }
+
+    /**
+     * It prints current node.
+     * 
+     * @param node
+     *            is the current node
+     * @param template
+     *            is the template to evaluate for each node
+     * @return the current node
+     */
+    public ENode trace(ENode node, String template) {
+        trace++;
+        String prefix;
+        if (template != null && template.length() > 0) {
+            try {
+                prefix = Conventions.formatString(template) + '=' + Conventions.formatString(evaluate(node, template).toString());
+            } catch (TemplateSyntaxException e) {
+                prefix = ""; //$NON-NLS-1$
+            } catch (FactoryException e) {
+                prefix = ""; //$NON-NLS-1$
+            }
+        } else {
+            prefix = ""; //$NON-NLS-1$
+        }
+        String marker = ('[' + trace + "]          ").substring(0, 10); //$NON-NLS-1$
+        System.out.println(marker + prefix + ' ' + AcceleoGenMessages.getString("ENodeServices.TraceMessage", new Object[] { node.getType(), Conventions.formatString(node.toString()), })); //$NON-NLS-1$
+        return node;
+    }
+
+    private int trace = 0;
+
+    private ENode evaluate(ENode current, String call) throws TemplateSyntaxException, FactoryException {
+        int pos = getBegin();
+        call = call.replaceAll("'", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateExpression expression = TemplateExpression.fromString(computeCall(pos, call), new Int2(pos, pos + call.length()), script);
+        try {
+            return expression.evaluate(current, script, LaunchManager.create("run", true)); //$NON-NLS-1$
+        } catch (ENodeException e) {
+            return new ENode(ENode.EMPTY, current);
+        }
+    }
+
+    private int getBegin() {
+        Int2 pos = (Int2) script.contextPeek(IScript.ARGUMENT_POSITION);
+        if (pos != null) {
+            return pos.b();
+        } else {
+            return 0;
+        }
+    }
+
+    private String computeCall(int begin, String call) {
+        if (begin > 0) {
+            StringBuffer result = new StringBuffer(""); //$NON-NLS-1$
+            for (int i = 0; i < begin; i++) {
+                result.append(' ');
+            }
+            result.append(call);
+            return result.toString();
+        } else {
+            return call;
+        }
+    }
+
+    /***************************************************************************
+     * 
+     * List Services
+     * 
+     **************************************************************************/
+
+    /**
+     * Returns the size of the node.
+     * 
+     * @param node
+     *            is the current node <li>isEObject() : return 1</li> <li>
+     *            isList() : return getList().size()</li> <li>isString() :
+     *            return getString().length()</li> <li>isBoolean() : return 1</li>
+     *            <li>isInt() : return 1</li> <li>isNull() : return 0</li>
+     * @return value size
+     */
+    public int nSize(ENode node) {
+        return node.size();
+    }
+
+    /**
+     * Returns the child node at the given index in the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @param index
+     *            is the index of the child
+     * @return the child node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nGet(ENode node, int index) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENode result = list.get(index);
+            if (result != null) {
+                return result;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else if (index == 0) {
+            return node;
+        } else {
+            return new ENode(ENode.EMPTY, node);
+        }
+    }
+
+    /**
+     * Returns the children in the given range.
+     * 
+     * @param node
+     *            is the current node
+     * @param begin
+     *            is the beginning index
+     * @param begin
+     *            is the ending index
+     * @return the children in the given range
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nGet(ENode node, int begin, int end) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENodeList result = new ENodeList();
+            for (int i = begin; i < list.size() && (i < end || end == -1); i++) {
+                ENode child = list.get(i);
+                result.add(child);
+            }
+            return new ENode(result, node);
+        } else if (begin == 0 && (end > 0 || end == -1)) {
+            return node;
+        } else {
+            return new ENode(ENode.EMPTY, node);
+        }
+    }
+
+    /**
+     * Returns the first child of the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the first child node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nFirst(ENode node) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENode result = list.get(0);
+            if (result != null) {
+                return result;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Returns the last child of the current node.
+     * 
+     * @param node
+     *            is the current node
+     * @return the last child node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nLast(ENode node) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList list = node.getList();
+            ENode result = list.get(list.size() - 1);
+            if (result != null) {
+                return result;
+            } else {
+                return new ENode(ENode.EMPTY, node);
+            }
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Removes all duplicated nodes.
+     * 
+     * @param node
+     *            is the current node
+     * @return the minimized node
+     * @throws ENodeCastException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode minimize(ENode node) throws ENodeCastException {
+        return nMinimize(node);
+    }
+
+    /**
+     * Removes all duplicated nodes.
+     * 
+     * @param node
+     *            is the current node
+     * @return the minimized node
+     * @throws ENodeCastException
+     */
+    public ENode nMinimize(ENode node) throws ENodeCastException {
+        if (node.isList()) {
+            ENodeList result = new ENodeList(true);
+            result.addAll(node.getList());
+            return new ENode(result, node);
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Reverses the order of the elements of the specified node.
+     * 
+     * @param node
+     *            is the node whose elements are to be reversed
+     * @return the new node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode reverse(ENode node) throws ENodeCastException, FactoryException {
+        return nReverse(node);
+    }
+
+    /**
+     * Reverses the order of the elements of the specified node.
+     * 
+     * @param node
+     *            is the node whose elements are to be reversed
+     * @return the new node
+     * @throws ENodeCastException
+     * @throws FactoryException
+     */
+    public ENode nReverse(ENode node) throws ENodeCastException, FactoryException {
+        if (node.isList()) {
+            ENodeList result = new ENodeList();
+            ENodeIterator it = node.getList().iterator();
+            while (it.hasNext()) {
+                ENode child = it.next();
+                if (!child.isNull()) {
+                    result.add(0, child);
+                }
+            }
+            return new ENode(result, node);
+        } else {
+            return node;
+        }
+    }
+
+    /**
+     * Returns true if this list contains the specified element.
+     * <p>
+     * More formally, returns true if and only if this list contains at least
+     * <p>
+     * one element e such that (o==null ? e==null : o.equals(e)).
+     * 
+     * @param node
+     *            is the current node
+     * @param element
+     *            is element whose presence in this list is to be tested
+     * @return true if this list contains the specified element
+     * @throws ENodeCastException
+     */
+    public boolean nContains(ENode node, ENode element) throws ENodeCastException {
+        if (node.isList()) {
+            return node.getList().contains(element);
+        } else {
+            return node.equals(element);
+        }
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param node
+     *            is the current node
+     * @return the sorted node
+     * @throws ENodeCastException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode sort(ENode node) throws ENodeCastException {
+        return nMinimize(nSort(node));
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param node
+     *            is the current node
+     * @return the sorted node
+     * @throws ENodeCastException
+     */
+    public ENode nSort(ENode node) throws ENodeCastException {
+        if (node.isList()) {
+            node.getList().sort();
+        }
+        return node;
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to evaluate for each node
+     * @return the sorted node
+     * @throws ENodeCastException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode sort(ENode current, String call) throws ENodeCastException {
+        return nMinimize(nSort(current, call));
+    }
+
+    /**
+     * Sorts the node and its children.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to evaluate for each node
+     * @return the sorted node
+     * @throws ENodeCastException
+     */
+    public ENode nSort(ENode current, String call) throws ENodeCastException {
+        final String template = call;
+        if (current.isList()) {
+            Set set = new TreeSet(new Comparator() {
+                public int compare(Object arg0, Object arg1) {
+                    ENode n0;
+                    try {
+                        n0 = evaluate((ENode) arg0, template);
+                    } catch (TemplateSyntaxException e) {
+                        n0 = new ENode(ENode.EMPTY, (ENode) arg0);
+                    } catch (FactoryException e) {
+                        n0 = new ENode(ENode.EMPTY, (ENode) arg0);
+                    }
+                    ENode n1;
+                    try {
+                        n1 = evaluate((ENode) arg1, template);
+                    } catch (TemplateSyntaxException e) {
+                        n1 = new ENode(ENode.EMPTY, (ENode) arg1);
+                    } catch (FactoryException e) {
+                        n1 = new ENode(ENode.EMPTY, (ENode) arg1);
+                    }
+                    return n0.compareTo(n1);
+                }
+            });
+            ENodeIterator it = current.getList().iterator();
+            while (it.hasNext()) {
+                set.add(it.next());
+            }
+            ENodeList result = new ENodeList();
+            Iterator elements = set.iterator();
+            while (elements.hasNext()) {
+                result.add((ENode) elements.next());
+            }
+            return new ENode(result, current);
+        } else {
+            return current;
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/EObjectServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/EObjectServices.java
new file mode 100644
index 0000000..70559fe
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/EObjectServices.java
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.EFactory;
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.ecore.tools.ETools;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.tools.resources.FileContentMap;
+
+/**
+ * System services for EObject elements.
+ * 
+ * 
+ */
+public class EObjectServices {
+
+    /**
+     * Constructor. For non eAllContents operations.
+     * 
+     */
+    public EObjectServices() {
+        // nothing to do here
+    }
+
+    /**
+     * The script.
+     */
+    protected IScript script;
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public EObjectServices(IScript script) {
+        this.script = script;
+        if (script instanceof SpecificScript) {
+            addMetamodel(((SpecificScript) script).getMetamodel());
+        }
+    }
+
+    /**
+     * Initialize eAllContents maps for the given metamodel root package.
+     * 
+     * @param metamodel
+     *            the root package of a metamodel
+     */
+    protected void addMetamodel(EPackage metamodel) {
+        if (!eRootPackages.contains(metamodel)) {
+            listClassifiers(metamodel);
+            eRootPackages.add(metamodel);
+        }
+    }
+
+    /**
+     * Gets the container of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the container
+     */
+    public EObject eContainer(EObject current) {
+        return current.eContainer();
+    }
+
+    /**
+     * Gets recursively the container of an EObject. The recursivity is stopped
+     * when an element of the given type is found.
+     * 
+     * @throws FactoryException
+     */
+    public EObject eContainer(EObject current, String type) throws FactoryException {
+        while (current != null) {
+            if (EFactory.eInstanceOf(current, type)) {
+                return current;
+            } else {
+                current = current.eContainer();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the root container; it may be this object itself and it will have
+     * a <code>null</code> {@link EObject#eContainer container}.
+     * <p>
+     * The root container must be {@link Resource#getContents directly
+     * contained} in a resource for its {@link EObject#eAllContents tree} to be
+     * {@link Resource#save(java.util.Map) serializable}.
+     * </p>
+     * 
+     * @param eObject
+     *            the object to get the root container for.
+     * @return the root container.
+     */
+    public EObject getRootContainer(EObject eObject) {
+        return EcoreUtil.getRootContainer(eObject);
+    }
+
+    /**
+     * Gets the metamodel class of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the metamodel class
+     */
+    public EObject eClass(EObject current) {
+        return current.eClass();
+    }
+
+    /**
+     * Gets the children of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the children
+     */
+    public EList eContents(EObject current) {
+        return current.eContents();
+    }
+
+    /**
+     * Gets all the direct contents and indirect contents of this object.
+     * 
+     * @param current
+     *            is the object
+     * @return the contents
+     */
+    public ENodeList eAllContents(ENode current) {
+        ENodeList result = new ENodeList();
+        try {
+            if (current.isList()) {
+                ENodeIterator it = current.getList().iterator();
+                while (it.hasNext()) {
+                    result.addAll(eAllContents(it.next()));
+                }
+            } else if (current.isEObject()) {
+                TreeIterator it = current.getEObject().eAllContents();
+                while (it.hasNext()) {
+                    result.add(ENode.createTry(it.next(), current));
+                }
+            }
+        } catch (ENodeCastException e) {
+            // Never catch
+        }
+        return result;
+    }
+
+    /**
+     * Gets all the direct contents and indirect contents of the object.
+     * 
+     * @param current
+     *            is the object
+     * @param type
+     *            is the type of the objects to select
+     * @return the contents
+     * @throws FactoryException
+     */
+    public ENodeList eAllContents(ENode current, String type) throws FactoryException {
+        ENodeList result = new ENodeList();
+        try {
+            if (current.isList()) {
+                ENodeIterator it = current.getList().iterator();
+                while (it.hasNext()) {
+                    result.addAll(eAllContents(it.next(), type));
+                }
+            } else if (current.isEObject()) {
+                StringBuffer buffer = new StringBuffer();
+                Resource eResource = current.getEObject().eResource();
+                if (eResource != null) {
+                    buffer.append(eResource.getURI().path());
+                    buffer.append(':');
+                    buffer.append(eResource.getURIFragment(current.getEObject()));
+                } else {
+                    buffer.append(':');
+                    buffer.append(ETools.getURI(current.getEObject()));
+                }
+                buffer.append(':');
+                buffer.append(type);
+                String uri = buffer.toString();
+                List children = (List) eAllContents.get(uri);
+                if (children == null) {
+                    int i = type.lastIndexOf("."); //$NON-NLS-1$
+                    String typeName = i > -1 ? type.substring(i + 1) : type;
+                    children = eAllContents(current.getEObject(), type, typeName);
+                    eAllContents.put(uri, children);
+                }
+                Iterator it = children.iterator();
+                while (it.hasNext()) {
+                    result.add(ENode.createTry(it.next(), current));
+                }
+            }
+        } catch (ENodeCastException e) {
+            // Never catch
+        }
+        return result;
+    }
+
+    private Map eAllContents = new WeakHashMap();
+
+    private List eRootPackages = new ArrayList();
+
+    private Map eClass2containments = new HashMap();
+
+    private Map eClass2subTypes = null;
+
+    private List eAllContents(EObject object, String type, String typeName) {
+        List result = new ArrayList();
+        List containmentTypeNames = getContainmentNames(object);
+        if (containmentTypeNames.contains(typeName)) {
+            Iterator eContents = object.eContents().iterator();
+            while (eContents.hasNext()) {
+                EObject eContent = (EObject) eContents.next();
+                if (EFactory.eInstanceOf(eContent, type)) {
+                    result.add(eContent);
+                }
+                result.addAll(eAllContents(eContent, type, typeName));
+            }
+        }
+        return result;
+    }
+
+    private List getContainmentNames(EObject object) {
+        EClass eClass = object.eClass();
+        EPackage ePackage = (EPackage) getRootContainer(eClass);
+        addMetamodel(ePackage);
+        String eClassName = eClass.getName();
+        List containmentNames = (List) eClass2containments.get(eClassName);
+        if (containmentNames == null) {
+            containmentNames = new ArrayList();
+            computeContainments(new ArrayList(), containmentNames, ePackage, eClass.getEAllReferences());
+            eClass2containments.put(eClassName, containmentNames);
+        }
+        return containmentNames;
+    }
+
+    private void computeContainments(List containmentTypes, List containmentNames, EPackage ePackage, List eReferences) {
+        Iterator references = eReferences.iterator();
+        while (references.hasNext()) {
+            EReference eReference = (EReference) references.next();
+            if (eReference.isContainment()) {
+                Set types = new HashSet();
+                types.add(eReference.getEType());
+                if (eReference.getEType() instanceof EClass) {
+                    types.addAll(((EClass) eReference.getEType()).getEAllSuperTypes());
+                }
+                Iterator subTypes = eClass2subTypes(ePackage, eReference.getEType()).iterator();
+                while (subTypes.hasNext()) {
+                    EClassifier subType = (EClassifier) subTypes.next();
+                    types.add(subType);
+                    if (subType instanceof EClass) {
+                        Iterator it = ((EClass) subType).getEAllSuperTypes().iterator();
+                        while (it.hasNext()) {
+                            EClassifier superType = (EClassifier) it.next();
+                            String name = superType.getName();
+                            if (!containmentNames.contains(name)) {
+                                containmentNames.add(name);
+                            }
+                        }
+                    }
+                }
+                Iterator it = types.iterator();
+                while (it.hasNext()) {
+                    EClassifier type = (EClassifier) it.next();
+                    if (type instanceof EClass) {
+                        String name = type.getName();
+                        if (!containmentTypes.contains(type)) {
+                            containmentTypes.add(type);
+                            if (!containmentNames.contains(name)) {
+                                containmentNames.add(name);
+                            }
+                            computeContainments(containmentTypes, containmentNames, ePackage, ((EClass) type).getEReferences());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private List eClass2subTypes(EPackage ePackage, EClassifier eClass) {
+        if (eClass2subTypes == null) {
+            eClass2subTypes = new HashMap();
+        }
+        List types = (List) eClass2subTypes.get(eClass);
+        if (types == null) {
+            types = new ArrayList();
+        }
+        return types;
+    }
+
+    private void listClassifiers(EPackage ePackage) {
+        Iterator classifiers = ETools.computeAllClassifiersList(ePackage, false).iterator();
+
+        if (eClass2subTypes == null) {
+            eClass2subTypes = new HashMap();
+        }
+        while (classifiers.hasNext()) {
+            Object next = classifiers.next();
+            if (next instanceof EClass) {
+                EClass c = (EClass) next;
+                Iterator superTypes = c.getEAllSuperTypes().iterator();
+                while (superTypes.hasNext()) {
+                    EClass superType = (EClass) superTypes.next();
+                    List subTypes = (List) eClass2subTypes.get(superType);
+                    if (subTypes == null) {
+                        subTypes = new ArrayList();
+                        eClass2subTypes.put(superType, subTypes);
+                    }
+                    if (!subTypes.contains(c)) {
+                        subTypes.add(c);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the containing feature of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the containing feature
+     */
+    public EStructuralFeature eContainingFeature(EObject current) {
+        return current.eContainingFeature();
+    }
+
+    /**
+     * Gets the containment feature of an EObject.
+     * 
+     * @param current
+     *            is the object
+     * @return the containment feature
+     */
+    public EReference eContainmentFeature(EObject current) {
+        return current.eContainmentFeature();
+    }
+
+    /**
+     * Gets the cross referenced objects.
+     * 
+     * @param current
+     *            is the object
+     * @return the cross referenced objects
+     */
+    public List eCrossReferences(EObject current) {
+        return current.eCrossReferences();
+    }
+
+    /**
+     * Gets the containing resource, or null.
+     * 
+     * @param current
+     *            is the object
+     * @return the resource
+     */
+    public String eResource(EObject current) {
+        if (current != null && current.eResource() != null) {
+            return current.eResource().getURI().path();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the containing resource name, or null.
+     * 
+     * @param current
+     *            is the object
+     * @return the resource
+     */
+    public String eResourceName(EObject current) {
+        if (current != null && current.eResource() != null) {
+            return current.eResource().getURI().lastSegment();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Loads the root element of the given model.
+     * 
+     * @param node
+     *            is the current node
+     * @param path
+     *            is the path of the model to load
+     * @return the root element of the model
+     */
+    public EObject load(ENode node, String path) {
+        if (path.startsWith("/resource")) { //$NON-NLS-1$
+            path = path.substring("/resource".length()); //$NON-NLS-1$
+        }
+        IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
+        if (file.exists()) {
+            EObject result = (EObject) load.get(file);
+            if (result == null) {
+                result = ETools.loadXMI(path);
+                load.put(file, result);
+            }
+            return result;
+        } else {
+            return ETools.loadXMI(path);
+        }
+    }
+
+    private FileContentMap load = new FileContentMap();
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ExternalServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ExternalServices.java
new file mode 100644
index 0000000..a717c27
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ExternalServices.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExternalServices {
+
+    /**
+     * get all external services registered.
+     * 
+     * @return List
+     */
+
+    public List getAllExternalServices() {
+        final List services = new ArrayList();
+
+        return services;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/PropertiesServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/PropertiesServices.java
new file mode 100644
index 0000000..0c46ef4
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/PropertiesServices.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+
+/**
+ * System services for the properties files.
+ * 
+ * 
+ */
+public class PropertiesServices {
+
+    /**
+     * The script.
+     */
+    protected SpecificScript script;
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public PropertiesServices(SpecificScript script) {
+        this.script = script;
+    }
+
+    /**
+     * Gets the value for the key in all the property files.
+     * 
+     * @param current
+     *            is the current node
+     * @param key
+     *            is the key
+     * @return the value for the given key
+     * @throws CoreException
+     * @throws IOException
+     */
+    public ENode getProperty(ENode current, String key) throws CoreException, IOException {
+        String result = script.getProperty(key);
+        return new ENode(result, current);
+    }
+
+    /**
+     * Gets the property for the key and the property file (without extension).
+     * 
+     * @param current
+     *            is the current node
+     * @param name
+     *            is the name of the property file (without ".properties"
+     *            extension)
+     * @param key
+     *            is the key
+     * @return the value for the given key
+     * @throws CoreException
+     * @throws IOException
+     */
+    public ENode getProperty(ENode current, String name, String key) throws CoreException, IOException {
+        String result = script.getProperty(name, key);
+        return new ENode(result, current);
+    }
+
+    /**
+     * Gets the best value for the key in all the property files.
+     * <p>
+     * Sample : key == "aa.bb.cc.dd"
+     * <p>
+     * It returns getProperty("aa.bb.cc.dd") || getProperty("aa.bb.cc") ||
+     * getProperty("aa.bb") || getProperty("aa").
+     * 
+     * @param current
+     *            is the current node
+     * @param key
+     *            is the key
+     * @return the value for the given key
+     * @throws CoreException
+     * @throws IOException
+     */
+    public ENode getBestProperty(ENode current, String key) throws CoreException, IOException {
+        String result = null;
+        while (result == null && key != null && key.length() > 0) {
+            result = script.getProperty(key);
+            if (result == null) {
+                int i = key.lastIndexOf("."); //$NON-NLS-1$
+                if (i == -1) {
+                    key = null;
+                } else {
+                    key = key.substring(0, i);
+                }
+            }
+        }
+        return new ENode(result, current);
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/RequestServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/RequestServices.java
new file mode 100644
index 0000000..0930477
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/RequestServices.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * Request services.
+ * 
+ * 
+ */
+public class RequestServices {
+
+    /**
+     * The script.
+     */
+    protected IScript script;
+
+    /**
+     * Constructor.
+     * 
+     * @param script
+     *            is the script
+     */
+    public RequestServices(IScript script) {
+        this.script = script;
+    }
+
+    /**
+     * Evaluates the given expression on all the elements of the current node
+     * and keep the elements validating the condition.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the condition
+     * @return valid elements
+     * @throws FactoryException
+     * @throws ENodeCastException
+     * @throws TemplateSyntaxException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode select(ENode current, String call) throws FactoryException, ENodeCastException, TemplateSyntaxException {
+        return select(current, call, new ENode(true, current));
+    }
+
+    /**
+     * Evaluates the given expression on all the elements of the current node
+     * and keep the elements validating the given value.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to apply
+     * @param value
+     *            is the value of the elements to keep
+     * @return valid elements
+     * @throws FactoryException
+     * @throws ENodeCastException
+     * @throws TemplateSyntaxException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode select(ENode current, String call, ENode value) throws FactoryException, ENodeCastException, TemplateSyntaxException {
+        int pos = getBegin();
+        call = call.replaceAll("'", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateExpression expression = TemplateExpression.fromString(computeCall(pos, call), new Int2(pos, pos + call.length()), script);
+        return select(current, expression, value);
+    }
+
+    private ENode select(ENode current, TemplateExpression call, ENode value) throws FactoryException, ENodeCastException {
+        if (current.isList()) {
+            ENodeList list = current.getList();
+            ENodeList res = new ENodeList();
+            ENodeIterator it = list.iterator();
+            while (it.hasNext()) {
+                res.add(select(it.next(), call, value));
+            }
+            return new ENode(res, current);
+        } else {
+            try {
+                ENode result = call.evaluate(current, script, LaunchManager.create("run", true)); //$NON-NLS-1$
+                if (result.equals(value)) {
+                    return current;
+                } else {
+                    return new ENode(ENode.EMPTY, current);
+                }
+            } catch (ENodeException e) {
+                return new ENode(ENode.EMPTY, current);
+            }
+        }
+    }
+
+    /**
+     * Evaluates the given expression on all the elements of the current node
+     * and delete the elements validating the condition.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to apply
+     * @return valid elements
+     * @throws FactoryException
+     * @throws ENodeCastException
+     * @throws TemplateSyntaxException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode delete(ENode current, String call) throws FactoryException, ENodeCastException, TemplateSyntaxException {
+        return delete(current, call, new ENode(true, current));
+    }
+
+    /**
+     * Evaluates the given expression on all the elements of the current node
+     * and delete the elements validating the given value.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to apply
+     * @param value
+     *            is the value of the elements to delete
+     * @return valid elements
+     * @throws FactoryException
+     * @throws ENodeCastException
+     * @throws TemplateSyntaxException
+     * @deprecated
+     */
+    @Deprecated
+    public ENode delete(ENode current, String call, ENode value) throws FactoryException, ENodeCastException, TemplateSyntaxException {
+        int pos = getBegin();
+        call = call.replaceAll("'", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateExpression expression = TemplateExpression.fromString(computeCall(pos, call), new Int2(pos, pos + call.length()), script);
+        return delete(current, expression, value);
+    }
+
+    private ENode delete(ENode current, TemplateExpression call, ENode value) throws FactoryException, ENodeCastException {
+        if (current.isList()) {
+            ENodeList list = current.getList();
+            ENodeList res = new ENodeList();
+            ENodeIterator it = list.iterator();
+            while (it.hasNext()) {
+                res.add(delete(it.next(), call, value));
+            }
+            return new ENode(res, current);
+        } else {
+            try {
+                ENode result = call.evaluate(current, script, LaunchManager.create("run", true)); //$NON-NLS-1$
+                if (!result.equals(value)) {
+                    return current;
+                } else {
+                    return new ENode(ENode.EMPTY, current);
+                }
+            } catch (ENodeException e) {
+                return new ENode(ENode.EMPTY, current);
+            }
+        }
+    }
+
+    /**
+     * Evaluates the given text as an acceleo expression.
+     * 
+     * @param current
+     *            is the current node of generation
+     * @param call
+     *            is the expression to evaluate
+     * @return evaluation
+     * @throws TemplateSyntaxException
+     * @throws FactoryException
+     */
+    public ENode evaluate(ENode current, String call) throws TemplateSyntaxException, FactoryException {
+        int pos = getBegin();
+        call = call.replaceAll("'", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$
+        TemplateExpression expression = TemplateExpression.fromString(computeCall(pos, call), new Int2(pos, pos + call.length()), script);
+        try {
+            return expression.evaluate(current, script, LaunchManager.create("run", true)); //$NON-NLS-1$
+        } catch (ENodeException e) {
+            return new ENode(ENode.EMPTY, current);
+        }
+    }
+
+    private int getBegin() {
+        Int2 pos = (Int2) script.contextPeek(IScript.ARGUMENT_POSITION);
+        if (pos != null) {
+            return pos.b();
+        } else {
+            return 0;
+        }
+    }
+
+    private String computeCall(int begin, String call) {
+        if (begin > 0) {
+            StringBuffer result = new StringBuffer(""); //$NON-NLS-1$
+            for (int i = 0; i < begin; i++) {
+                result.append(' ');
+            }
+            result.append(call);
+            return result.toString();
+        } else {
+            return call;
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ResourceServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ResourceServices.java
new file mode 100644
index 0000000..39d91d5
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/ResourceServices.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+/**
+ * Eclipse resource services.
+ * 
+ * 
+ */
+public class ResourceServices {
+
+    /**
+     * Returns the content of the given file.
+     * 
+     * @param node
+     *            is the current node
+     * @param path
+     *            is the path of the file in the workspace
+     * @return the content of the file, or an empty buffer if the file doesn't
+     *         exist
+     */
+    public String getFileContent(ENode node, String path) {
+        IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
+        if (file.exists()) {
+            return Resources.getFileContent(file).toString();
+        } else {
+            return ""; //$NON-NLS-1$
+        }
+    }
+
+    public String getChainPath(ENode node) {
+        String res = ""; //$NON-NLS-1$
+        IScript script = node.getContainerTemplateElement().getScript();
+        if (script instanceof SpecificScript) {
+            File chain = ((SpecificScript) script).getChainFile();
+            if (chain != null) {
+                res = Resources.makeWorkspaceRelativePath(chain.getAbsolutePath());
+            }
+        }
+        return res;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/StringServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/StringServices.java
new file mode 100644
index 0000000..1585b1b
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/StringServices.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+
+/**
+ * System services for String elements.
+ * 
+ * 
+ */
+public class StringServices {
+
+    /**
+     * Returns the string's length
+     * 
+     * @param s
+     *            is the string
+     * @return the string's length
+     */
+    public int length(String s) {
+        return s.length();
+    }
+
+    /**
+     * Returns an upper case representation of a string.
+     * 
+     * @param node
+     *            is the current node
+     * @return the upper case representation
+     */
+    public ENode toUpperCase(ENode node) {
+        node.stringCall("toUpperCase", -1, -1); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Returns a lower case representation of a string.
+     * 
+     * @param node
+     *            is the current node
+     * @return the lower case representation
+     */
+    public ENode toLowerCase(ENode node) {
+        node.stringCall("toLowerCase", -1, -1); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Translates the first character of the given string to upper case.
+     * 
+     * @param node
+     *            is the current node
+     * @return the upper case representation
+     */
+    public ENode toU1Case(ENode node) {
+        node.stringCall("toU1Case", -1, -1); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Translates the first character of the given string to lower case.
+     * 
+     * @param node
+     *            is the current node
+     * @return the lower case representation
+     */
+    public ENode toL1Case(ENode node) {
+        node.stringCall("toL1Case", -1, -1); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Returns a substring of a string that begins at a specified index and ends
+     * at end - 1.
+     * 
+     * @param node
+     *            is the current node
+     * @param begin
+     *            is the beginning index, inclusive
+     * @param end
+     *            is the ending index, exclusive
+     * @return the substring
+     */
+    public ENode substring(ENode node, int begin, int end) {
+        node.stringCall("substring", begin, end); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Gets a substring of a string that begins at a specified index and ends at
+     * the end of the string.
+     * 
+     * @param node
+     *            is the current node
+     * @param begin
+     *            is the beginning index, inclusive
+     * @return the substring
+     */
+    public ENode substring(ENode node, int begin) {
+        node.stringCall("substring", begin, -1); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Replaces all occurences of substring by another substring in a string.
+     * 
+     * @param buffer
+     *            is the buffer
+     * @param s1
+     *            is the substring to replace
+     * @param s2
+     *            is the new substring
+     * @return the new string
+     */
+    public String replaceAll(String buffer, String s1, String s2) {
+        return buffer.replaceAll(s1, s2);
+    }
+
+    /**
+     * Replaces the first occurence of a substring by another substring in a
+     * string.
+     * 
+     * @param buffer
+     *            is the buffer
+     * @param s1
+     *            is the substring to replace
+     * @param s2
+     *            is the new substring
+     * @return the new string
+     */
+    public String replaceFirst(String buffer, String s1, String s2) {
+        return buffer.replaceFirst(s1, s2);
+    }
+
+    /**
+     * Removes leading and trailing spaces of a string.
+     * 
+     * @param node
+     *            is the current node
+     * @return the string without leading and trailing spaces
+     */
+    public ENode trim(ENode node) {
+        node.stringCall("trim", -1, -1); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Indicates if a string starts with a given substring.
+     * 
+     * @param s
+     *            is the string
+     * @param arg
+     *            is the substring
+     * @return true if the string starts with the given substring
+     */
+    public boolean startsWith(String s, String arg) {
+        return s.startsWith(arg);
+    }
+
+    /**
+     * Indicates if a string ends with a given substring.
+     * 
+     * @param s
+     *            is the string
+     * @param arg
+     *            is the substring
+     * @return true if the string ends with the given substring
+     */
+    public boolean endsWith(String s, String arg) {
+        return s.endsWith(arg);
+    }
+
+    /**
+     * Indicates if two strings are equal, ignoring case.
+     * 
+     * @param s
+     *            is the first string
+     * @param arg
+     *            is the second string
+     * @return true if the two strings are equal
+     */
+    public boolean equalsIgnoreCase(String s, String arg) {
+        return s.equalsIgnoreCase(arg);
+    }
+
+    /**
+     * Indicates if a string matches a regex.
+     * 
+     * @param s
+     *            is the string
+     * @param regex
+     *            is the regex
+     * @return true if the string matches with the given regex
+     */
+    public boolean matches(String s, String regex) {
+        return s.matches(regex);
+    }
+
+    /**
+     * Gets the char at a given position.
+     * 
+     * @param s
+     *            is the string
+     * @param index
+     *            is the position
+     * @return the char at the given position
+     */
+    public String charAt(String s, int index) {
+        return String.valueOf(s.charAt(index));
+    }
+
+    /**
+     * Returns the position of a substring in a string.
+     * 
+     * @param buffer
+     *            is the string
+     * @param arg
+     *            is the substring
+     * @return the position of the substring
+     */
+    public int indexOf(String buffer, String arg) {
+        return buffer.indexOf(arg);
+    }
+
+    /**
+     * Returns the position of a substring a the string, starting at a specified
+     * position.
+     * 
+     * @param buffer
+     *            is the string
+     * @param arg
+     *            is the substring
+     * @param index
+     *            is the position where the research starts form
+     * @return the position of the substring
+     */
+    public int indexOf(String buffer, String arg, int index) {
+        return buffer.indexOf(arg, index);
+    }
+
+    /**
+     * Returns the last position of a substring in a string.
+     * 
+     * @param buffer
+     *            is the string
+     * @param arg
+     *            is the substring
+     * @return the last position of the substring
+     */
+    public int lastIndexOf(String buffer, String arg) {
+        return buffer.lastIndexOf(arg);
+    }
+
+    /**
+     * Returns the last position of a substring in a string, starting at a
+     * specified position.
+     * 
+     * @param buffer
+     *            is the string
+     * @param arg
+     *            is the substring
+     * @param index
+     *            is the position where the research starts form
+     * @return the last position of the substring
+     */
+    public int lastIndexOf(String buffer, String arg, int index) {
+        return buffer.lastIndexOf(arg, index);
+    }
+
+    /**
+     * Splits a string with a substring.
+     * 
+     * @param buffer
+     *            is the string
+     * @param arg
+     *            is the substring
+     * @return a list that contains the splitted string
+     */
+    public List split(String buffer, String arg) {
+        String[] result = buffer.split(arg);
+        if (result == null) {
+            result = new String[0];
+        }
+        return Arrays.asList(result);
+    }
+
+    /**
+     * Indents a string with ' '.
+     * 
+     * @param node
+     *            is the current node
+     * @return the indented string
+     */
+    public ENode indentSpace(ENode node) {
+        node.stringCall("indentSpace", -1, -1); //$NON-NLS-1$
+        return node;
+    }
+
+    /**
+     * Indents a string with '\t'.
+     * 
+     * @param node
+     *            is the current node
+     * @return the indented string
+     */
+    public ENode indentTab(ENode node) {
+        node.stringCall("indentTab", -1, -1); //$NON-NLS-1$
+        return node;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/SystemServicesFactory.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/SystemServicesFactory.java
new file mode 100644
index 0000000..3d907ea
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/SystemServicesFactory.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EPackage;
+
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.SpecificScript;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.imports.EvalJavaService;
+
+/**
+ * Factory that imports the system services for the given script.
+ * 
+ * 
+ */
+public class SystemServicesFactory {
+
+    /**
+     * The instance of the root EObjectServices.
+     */
+    private EObjectServices eObjectServices;
+
+    private List metamodels;
+
+    /**
+     * Adds system imports to the given script.
+     * 
+     * @param script
+     *            is the script
+     * @param isRoot
+     *            indicates if the script is the root
+     */
+    public void addImports(IScript script, boolean isRoot) {
+        if (isRoot) {
+            script.addImport(new EvalJavaService(new StringServices(), false));
+            eObjectServices = new EObjectServices(script);
+            script.addImport(new EvalJavaService(eObjectServices, false));
+            if (metamodels != null) {
+                Iterator it = metamodels.iterator();
+                while (it.hasNext()) {
+                    eObjectServices.addMetamodel((EPackage) it.next());
+                }
+                metamodels = null;
+            }
+            script.addImport(new EvalJavaService(new XpathServices(), false));
+            script.addImport(new EvalJavaService(new ResourceServices(), false));
+            script.addImport(new EvalJavaService(new ContextServices(), false));
+        }
+        script.addImport(new EvalJavaService(new ENodeServices(script), true));
+        script.addImport(new EvalJavaService(new RequestServices(script), true));
+        if (script instanceof SpecificScript) {
+            if (eObjectServices != null) {
+                eObjectServices.addMetamodel(((SpecificScript) script).getMetamodel());
+            } else {
+                if (metamodels == null) {
+                    metamodels = new ArrayList();
+                }
+                metamodels.add(((SpecificScript) script).getMetamodel());
+            }
+            script.addImport(new EvalJavaService(new PropertiesServices((SpecificScript) script), true));
+            addExternalSystemServices(script); // registre external services as
+                                               // system services
+        }
+    }
+
+    /**
+     * allows to add user services as System Services
+     * 
+     * @param script
+     *            is the script
+     */
+    private void addExternalSystemServices(IScript script) {
+
+        final ExternalServices service = new ExternalServices();
+        final List services = service.getAllExternalServices();
+
+        for (int index = 0; index < services.size(); index++) {
+            script.addImport(new EvalJavaService(services.get(index), true));
+        }
+
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/XpathServices.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/XpathServices.java
new file mode 100644
index 0000000..01aaf1f
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/scripts/imports/services/XpathServices.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.scripts.imports.services;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * Xpath axes.
+ * 
+ * 
+ */
+public class XpathServices {
+
+    /**
+     * Same meaning as the "ancestor" axe in Xpath : selects all ancestors
+     * (parent, grandparent, etc.) of the current node
+     * 
+     * @param current
+     *            is the current node of generation
+     * @return all ancestors (parent, grandparent, etc.) of the current node
+     */
+    public List ancestor(EObject object) {
+        List result = new ArrayList();
+        object = object.eContainer();
+        while (object != null) {
+            result.add(object);
+            object = object.eContainer();
+        }
+        return result;
+    }
+
+    /**
+     * Same meaning as the "parent" axe in Xpath : selects the parent of the
+     * current node
+     * 
+     * @param current
+     *            is the current node of generation
+     * @return the parent of the current node
+     */
+    public EObject parent(EObject object) {
+        return object.eContainer();
+    }
+
+    /**
+     * Same meaning as the "self" axe in Xpath : selects the current node
+     * 
+     * @param current
+     *            is the current node of generation
+     * @return the current node
+     */
+    public EObject self(EObject object) {
+        return object;
+    }
+
+    /**
+     * Same meaning as the "child" axe in Xpath : selects all children of the
+     * current node
+     * 
+     * @param current
+     *            is the current node of generation
+     * @return all children of the current node
+     */
+    public List child(EObject object) {
+        return object.eContents();
+    }
+
+    /**
+     * Same meaning as the "descendant" axe in Xpath: Gets all the descendants
+     * (children, grandchildren, etc.) of the current node.
+     * 
+     * @param object
+     *            is the current node
+     * @return the descendants of the current node
+     */
+    public List descendant(EObject object) {
+        List result = new ArrayList();
+        TreeIterator it = object.eAllContents();
+        while (it.hasNext()) {
+            result.add(it.next());
+        }
+        return result;
+    }
+
+    /**
+     * Same meaning as the "preceding-sibling" axe in Xpath: selects all
+     * siblings before the current node.
+     * 
+     * @param object
+     *            is the current node
+     * @return all siblings before the current node
+     */
+    public List precedingSibling(EObject object) {
+        List result = new ArrayList();
+        EObject parent = object.eContainer();
+        if (parent != null) {
+            Iterator it = parent.eContents().iterator();
+            while (it.hasNext()) {
+                Object child = it.next();
+                if (child == object) {
+                    break;
+                } else {
+                    result.add(child);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Same meaning as the "preceding" axe in Xpath: selects everything in the
+     * model that is before the current node
+     * 
+     * @param object
+     *            is the current node
+     * @return everything in the model that is before the current node
+     */
+    public List preceding(EObject object) {
+        List result = new ArrayList();
+        List ancestors = ancestor(object);
+        ancestors.add(object);
+        // now return all preceding siblings and their respective children...
+        Iterator it = ancestors.iterator();
+        while (it.hasNext()) {
+            EObject parent = (EObject) it.next();
+            if (parent != object) {
+                result.add(parent);
+            }
+            result.addAll(precedingSibling(parent));
+            Iterator it2 = precedingSibling(parent).iterator();
+            while (it2.hasNext()) {
+                result.addAll(descendant((EObject) it2.next()));
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Same meaning as the "following-sibling" axe in Xpath: selects all
+     * siblings after the current node
+     * 
+     * @param object
+     *            is the current node
+     * @return all siblings after the current node
+     */
+    public List followingSibling(EObject object) {
+        List result = new ArrayList();
+        EObject parent = object.eContainer();
+        Iterator it = parent.eContents().iterator();
+        while (it.hasNext()) {
+            Object child = it.next();
+            if (child == object) {
+                break;
+            }
+        }
+        while (it.hasNext()) {
+            result.add(it.next());
+        }
+        return result;
+    }
+
+    /**
+     * Same meaning as the "following" axe in Xpath: selects everything in the
+     * model after the current node
+     * 
+     * @param object
+     *            is the current node
+     * @return everything after the current node
+     */
+    public List following(EObject object) {
+        List result = new ArrayList();
+        Iterator it = followingSibling(object).iterator();
+        while (it.hasNext()) {
+            EObject following = (EObject) it.next();
+            result.add(following);
+            result.addAll(descendant(following));
+        }
+        return result;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateCommentStatement.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateCommentStatement.java
new file mode 100644
index 0000000..d9bfe08
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateCommentStatement.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.statements;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateNodeElement;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * This is a comment statement for the generation tool. The generator didn't use
+ * this statement.
+ * 
+ * 
+ */
+public class TemplateCommentStatement extends TemplateNodeElement {
+
+    /**
+     * The text of the comment.
+     */
+    protected String comment;
+
+    /**
+     * Constructor.
+     * 
+     * @param comment
+     *            is the text of the comment
+     * @param script
+     *            is the script
+     */
+    public TemplateCommentStatement(String comment, IScript script) {
+        super(script);
+        this.comment = comment;
+    }
+
+    /**
+     * @return the comment
+     */
+    public String getComment() {
+        return comment;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        ENode result = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+        return result;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return TemplateConstants.COMMENT_BEGIN + comment + TemplateConstants.COMMENT_END;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getOutlineText() {
+        return toString();
+    }
+
+    /**
+     * It checks the syntax and creates a statement for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param buffer
+     *            is the textual representation of the templates
+     * @param limits
+     *            delimits the part of the text to be parsed for this statement
+     * @param script
+     *            is the generator's configuration
+     * @return the new statement
+     * @throws TemplateSyntaxException
+     */
+    public static TemplateNodeElement fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        TemplateCommentStatement element = new TemplateCommentStatement(buffer.substring(limits.b(), limits.e()), script);
+        element.setPos(limits);
+        return element;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateFeatureStatement.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateFeatureStatement.java
new file mode 100644
index 0000000..cb3db67
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateFeatureStatement.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.statements;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateNodeElement;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalFailure;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+
+/**
+ * This is a 'feature' statement for the generation tool. It is a kind of
+ * statement that contains one expression. This expression is evaluated to
+ * generate text.
+ * 
+ * 
+ */
+public class TemplateFeatureStatement extends TemplateNodeElement {
+
+    /**
+     * The expression.
+     */
+    protected TemplateExpression expression;
+
+    /**
+     * Constructor.
+     * 
+     * @param expression
+     *            is the expression
+     * @param script
+     *            is the script
+     */
+    public TemplateFeatureStatement(TemplateExpression expression, IScript script) {
+        super(script);
+        this.expression = expression;
+        this.expression.setParent(this);
+    }
+
+    /**
+     * @return the expression
+     */
+    public TemplateExpression getExpression() {
+        return expression;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        try {
+            ENode result = evaluateSub(object, mode);
+            return result;
+        } catch (ENodeException e) {
+            ENode result = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+            result.log().addError(new EvalFailure(e.getMessage()));
+            return result;
+        }
+    }
+
+    private ENode evaluateSub(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        ENode current = new ENode(object, this, mode.isSynchronize());
+        script.contextPush(IScript.CURRENT_NODE, current);
+        try {
+            ENode node = expression.evaluate(current, script, mode);
+            if (node.isNull() && !node.isOptional()) {
+                if (node.log().hasError()) {
+                    return node;
+                } else {
+                    throw new ENodeException(AcceleoGenMessages.getString("ENodeError.EmptyEvaluation"), expression.getPos(), expression.getScript(), object, false); //$NON-NLS-1$
+                }
+            } else {
+                return node;
+            }
+        } finally {
+            script.contextPop(IScript.CURRENT_NODE);
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return TemplateConstants.FEATURE_BEGIN + expression.toString() + TemplateConstants.FEATURE_END;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getOutlineText() {
+        return expression.toString();
+    }
+
+    /**
+     * It checks the syntax and creates a statement for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param buffer
+     *            is the textual representation of the templates
+     * @param limits
+     *            delimits the part of the text to be parsed for this statement
+     * @param script
+     *            is the generator's configuration
+     * @return the new statement
+     * @throws TemplateSyntaxException
+     */
+    public static TemplateNodeElement fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        TemplateExpression expression = TemplateExpression.fromString(buffer, new Int2(limits.b(), limits.e()), script);
+        TemplateFeatureStatement element = new TemplateFeatureStatement(expression, script);
+        element.setPos(limits);
+        return element;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateForStatement.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateForStatement.java
new file mode 100644
index 0000000..508a727
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateForStatement.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.statements;
+
+import org.eclipse.emf.ecore.EEnumLiteral;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EcoreFactory;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.template.Template;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateNodeElement;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeIterator;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeList;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalFailure;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * This is a 'for' statement for the generation tool. It is a kind of statement
+ * that contains an expression and a template. The template is evaluated for
+ * each value returned by the evaluation of the expression.
+ * 
+ * 
+ */
+public class TemplateForStatement extends TemplateNodeElement {
+
+    /**
+     * The expression.
+     */
+    protected TemplateExpression condition;
+
+    /**
+     * Template that is evaluated for each value returned by the evaluation of
+     * the expression.
+     */
+    protected Template block;
+
+    /**
+     * Constructor.
+     * 
+     * @param condition
+     *            is the conditional expression
+     * @param block
+     *            is the template that is evaluated for each value returned by
+     *            the evaluation of the expression.
+     * @param script
+     *            is the script
+     */
+    public TemplateForStatement(TemplateExpression condition, Template block, IScript script) {
+        super(script);
+        this.condition = condition;
+        this.condition.setParent(this);
+        this.block = block;
+        this.block.setParent(this);
+    }
+
+    /**
+     * Gets the condition.
+     */
+    public TemplateExpression getCondition() {
+        return condition;
+    }
+
+    /**
+     * @return the block
+     */
+    public Template getBlock() {
+        return block;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        try {
+            final ENode result = evaluateSub(object, mode);
+            return result;
+        } catch (final ENodeException e) {
+            final ENode result = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+            result.log().addError(new EvalFailure(e.getMessage()));
+            return result;
+        }
+    }
+
+    private ENode evaluateSub(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        final ENode node = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+        final ENode all = condition.evaluate(new ENode(object, condition, mode.isSynchronize()), script, mode);
+        if (mode.getMode() == LaunchManager.DEBUG_MODE) {
+            node.log().getAll(all.log(), false);
+        }
+        if (!all.isNull()) {
+            boolean containsEObject;
+            ENodeIterator it;
+            if (all.isList()) {
+                try {
+                    containsEObject = false;
+                    it = all.getList().iterator();
+                    while (it.hasNext() && !containsEObject) {
+                        final ENode child = it.next();
+                        if (child.isEObject()) {
+                            containsEObject = true;
+                        }
+                    }
+                    it = all.getList().iterator();
+                } catch (final ENodeCastException e) {
+                    // Never catch
+                    containsEObject = false;
+                    it = new ENodeList().iterator();
+                }
+            } else if (all.isInt()) {
+                try {
+                    containsEObject = true;
+                    final ENodeList list = new ENodeList();
+                    final int count = all.getInt();
+                    for (int i = 0; i < count; i++) {
+                        list.add(new ENode(object, condition, mode.isSynchronize()));
+                    };
+                    it = list.iterator();
+                } catch (final ENodeCastException e) {
+                    // Never catch
+                    containsEObject = false;
+                    it = new ENodeList().iterator();
+                }
+            } else {
+                containsEObject = all.isEObject();
+                final ENodeList list = new ENodeList();
+                list.add(all);
+                it = list.iterator();
+            }
+            if (it.hasNext()) {
+                int iObject = 0;
+                while (it.hasNext()) {
+                    ENode child = it.next();
+                    if (!containsEObject) {
+                        if (child.isString()) {
+                            try {
+                                final EEnumLiteral literal = EcoreFactory.eINSTANCE.createEEnumLiteral();
+                                final String value = child.getString();
+                                literal.setName(value);
+                                literal.setLiteral(value);
+                                child = new ENode(literal, child);
+                            } catch (final ENodeCastException e) {
+                                // Never catch
+                            }
+                        } else if (child.isInt()) {
+                            try {
+                                final EEnumLiteral literal = EcoreFactory.eINSTANCE.createEEnumLiteral();
+                                final String value = String.valueOf(child.getInt());
+                                literal.setName(value);
+                                literal.setLiteral(value);
+                                child = new ENode(literal, child);
+                            } catch (final ENodeCastException e) {
+                                // Never catch
+                            }
+                        } else if (child.isDouble()) {
+                            try {
+                                final EEnumLiteral literal = EcoreFactory.eINSTANCE.createEEnumLiteral();
+                                final String value = String.valueOf(child.getDouble());
+                                literal.setName(value);
+                                literal.setLiteral(value);
+                                child = new ENode(literal, child);
+                            } catch (final ENodeCastException e) {
+                                // Never catch
+                            }
+                        } else if (child.isBoolean()) {
+                            try {
+                                final EEnumLiteral literal = EcoreFactory.eINSTANCE.createEEnumLiteral();
+                                final String value = String.valueOf(child.getBoolean());
+                                literal.setName(value);
+                                literal.setLiteral(value);
+                                child = new ENode(literal, child);
+                            } catch (final ENodeCastException e) {
+                                // Never catch
+                            }
+                        }
+                    }
+                    script.contextPush(IScript.CURRENT_NODE, child);
+                    script.contextPush(IScript.WHILE_INDEX, new Integer(iObject));
+                    try {
+                        if (child.isEObject()) {
+                            try {
+                                final ENode n = block.evaluate(child.getEObject(), mode);
+                                node.append(n);
+                            } catch (final ENodeCastException e) {
+                                // Never catch
+                            }
+                            ++iObject;
+                        } else if (containsEObject) {
+                            node.append(child);
+                        }
+                    } finally {
+                        script.contextPop(IScript.CURRENT_NODE);
+                        script.contextPop(IScript.WHILE_INDEX);
+                    }
+                }
+            }
+        }
+        return node;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return TemplateConstants.FOR_BEGIN + condition.toString() + TemplateConstants.FOR_THEN + block.toString() + TemplateConstants.FOR_END;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getOutlineText() {
+        return "for " + condition.toString(); //$NON-NLS-1$
+    }
+
+    /**
+     * It checks the syntax and creates a statement for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param buffer
+     *            is the textual representation of the templates
+     * @param limits
+     *            delimits the part of the text to be parsed for this statement
+     * @param script
+     *            is the generator's configuration
+     * @return the new statement
+     * @throws TemplateSyntaxException
+     */
+    public static TemplateNodeElement fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        TemplateExpression condition;
+        Template block;
+        final Int2 iThen = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.FOR_THEN, limits.b(), limits.e(), TemplateConstants.SPEC, TemplateConstants.INHIBS_EXPRESSION);
+        if (iThen.b() > -1) {
+            condition = TemplateExpression.fromString(buffer, new Int2(limits.b(), iThen.b()), script);
+            Int2 blockPos = new Int2(iThen.e(), limits.e());
+            blockPos = Template.formatTemplate(buffer, blockPos, 0);
+            block = Template.read(buffer, blockPos, script);
+        } else {
+            condition = TemplateExpression.fromString(buffer, new Int2(limits.b(), limits.e()), script);
+            block = new Template(script);
+        }
+        final TemplateForStatement element = new TemplateForStatement(condition, block, script);
+        element.setPos(limits);
+        return element;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateIfStatement.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateIfStatement.java
new file mode 100644
index 0000000..f433ad6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/gen/template/statements/TemplateIfStatement.java
@@ -0,0 +1,350 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.gen.template.statements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EObject;
+
+import org.eclipse.sirius.query.legacy.ecore.factories.FactoryException;
+import org.eclipse.sirius.query.legacy.gen.AcceleoGenMessages;
+import org.eclipse.sirius.query.legacy.gen.template.Template;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateConstants;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateNodeElement;
+import org.eclipse.sirius.query.legacy.gen.template.TemplateSyntaxException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENode;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeCastException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.ENodeException;
+import org.eclipse.sirius.query.legacy.gen.template.eval.LaunchManager;
+import org.eclipse.sirius.query.legacy.gen.template.eval.log.EvalFailure;
+import org.eclipse.sirius.query.legacy.gen.template.expressions.TemplateExpression;
+import org.eclipse.sirius.query.legacy.gen.template.scripts.IScript;
+import org.eclipse.sirius.query.legacy.tools.strings.Int2;
+import org.eclipse.sirius.query.legacy.tools.strings.TextSearch;
+
+/**
+ * This is a 'if' statement for the generation tool. It is a kind of statement
+ * that contains a conditional expression and two templates. If the conditional
+ * expression is validated then the first template is evaluated, else the second
+ * template is evaluated.
+ * 
+ * 
+ */
+public class TemplateIfStatement extends TemplateNodeElement {
+
+    /**
+     * The conditional expression.
+     */
+    protected TemplateExpression condition;
+
+    /**
+     * Template that is evaluated if the conditional expression is validated.
+     */
+    protected Template ifTemplate;
+
+    /**
+     * The expressions for all the "else if" conditions.
+     */
+    protected TemplateExpression[] elseIfConditions;
+
+    /**
+     * The "else if" templates.
+     */
+    protected Template[] elseIfTemplates;
+
+    /**
+     * Template that is evaluated if the conditional expression is not
+     * validated.
+     */
+    protected Template elseTemplate;
+
+    /**
+     * Constructor.
+     * 
+     * @param condition
+     *            is the conditional expression
+     * @param ifTemplate
+     *            is the template that is evaluated if the conditional
+     *            expression is validated
+     * @param elseTemplate
+     *            is the template that is evaluated if the conditional
+     *            expression is not validated.
+     * @param script
+     *            is the script
+     */
+    public TemplateIfStatement(TemplateExpression condition, Template ifTemplate, Template elseTemplate, IScript script) {
+        this(condition, ifTemplate, new TemplateExpression[] {}, new Template[] {}, elseTemplate, script);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param condition
+     *            is the conditional expression
+     * @param ifTemplate
+     *            is the template that is evaluated if the conditional
+     *            expression is validated
+     * @param elseIfConditions
+     *            are "else if" conditions
+     * @param elseIfTemplates
+     *            are "else if" templates
+     * @param elseTemplate
+     *            is the template that is evaluated if the conditional
+     *            expression is not validated.
+     * @param script
+     *            is the script
+     */
+    public TemplateIfStatement(TemplateExpression condition, Template ifTemplate, TemplateExpression[] elseIfConditions, Template[] elseIfTemplates, Template elseTemplate, IScript script) {
+        super(script);
+        this.condition = condition;
+        this.condition.setParent(this);
+        this.ifTemplate = ifTemplate;
+        this.ifTemplate.setParent(this);
+        this.elseIfConditions = elseIfConditions;
+        for (final TemplateExpression elseIfCondition : elseIfConditions) {
+            elseIfCondition.setParent(this);
+        }
+        this.elseIfTemplates = elseIfTemplates;
+        for (final Template elseIfTemplate : elseIfTemplates) {
+            elseIfTemplate.setParent(this);
+        }
+        this.elseTemplate = elseTemplate;
+        this.elseTemplate.setParent(this);
+    }
+
+    /**
+     * @return the conditional expression
+     */
+    public TemplateExpression getCondition() {
+        return condition;
+    }
+
+    /**
+     * @return the elseIf conditions
+     */
+    public TemplateExpression[] getElseIfConditions() {
+        return elseIfConditions;
+    }
+
+    /**
+     * @return the elseIf templates
+     */
+    public Template[] getElseIfTemplates() {
+        return elseIfTemplates;
+    }
+
+    /**
+     * @return the else template
+     */
+    public Template getElseTemplate() {
+        return elseTemplate;
+    }
+
+    /**
+     * @return the if template
+     */
+    public Template getIfTemplate() {
+        return ifTemplate;
+    }
+
+    /**
+     * Returns the conditional expression for the given template.
+     * 
+     * @return the conditional expression for the given template or null
+     */
+    public String getConditionText(Template template) {
+        if (template == ifTemplate) {
+            return condition.toString();
+        } else if (template == elseTemplate) {
+            return "else"; //$NON-NLS-1$
+        } else {
+            for (int i = 0; i < elseIfTemplates.length && i < elseIfConditions.length; i++) {
+                if (template == elseIfTemplates[i]) {
+                    return elseIfConditions[i].toString();
+                }
+            }
+            return ""; //$NON-NLS-1$
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public ENode evaluate(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        try {
+            final ENode result = evaluateSub(object, mode);
+            return result;
+        } catch (final ENodeException e) {
+            final ENode result = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+            result.log().addError(new EvalFailure(e.getMessage()));
+            return result;
+        }
+    }
+
+    private ENode evaluateSub(EObject object, LaunchManager mode) throws ENodeException, FactoryException {
+        final ENode node = new ENode(ENode.EMPTY, object, this, mode.isSynchronize());
+        boolean testOK = false;
+        ENode test = condition.evaluate(new ENode(object, condition, mode.isSynchronize()), script, mode);
+        if (mode.getMode() == LaunchManager.DEBUG_MODE) {
+            node.log().getAll(test.log(), false);
+        }
+        try {
+            testOK = test.getBoolean();
+        } catch (final ENodeCastException e) {
+            try {
+                final Object boolValue = test.getAdapterValue(boolean.class);
+                if (boolValue instanceof Boolean) {
+                    testOK = ((Boolean) boolValue).booleanValue();
+                } else {
+                    throw new ENodeException(AcceleoGenMessages.getString("ENodeError.BooleanRequired", new Object[] { test.getType(), }), condition.getPos(), script, object, true); //$NON-NLS-1$
+                }
+            } catch (final ENodeCastException ex) {
+                throw new ENodeException(ex.getMessage(), condition.getPos(), script, object, true);
+            }
+        }
+        if (testOK) {
+            node.append(ifTemplate.evaluate(object, mode));
+        } else {
+            for (int i = 0; !testOK && i < elseIfConditions.length; i++) {
+                final TemplateExpression elseIfCondition = elseIfConditions[i];
+                test = elseIfCondition.evaluate(new ENode(object, elseIfCondition, mode.isSynchronize()), script, mode);
+                if (mode.getMode() == LaunchManager.DEBUG_MODE) {
+                    node.log().getAll(test.log(), false);
+                }
+                try {
+                    testOK = test.getBoolean();
+                } catch (final ENodeCastException e) {
+                    try {
+                        final Object boolValue = test.getAdapterValue(boolean.class);
+                        if (boolValue instanceof Boolean) {
+                            testOK = ((Boolean) boolValue).booleanValue();
+                        } else {
+                            throw new ENodeException(AcceleoGenMessages.getString("ENodeError.BooleanRequired", new Object[] { test.getType(), }), elseIfCondition.getPos(), script, object, true); //$NON-NLS-1$
+                        }
+                    } catch (final ENodeCastException ex) {
+                        throw new ENodeException(ex.getMessage(), elseIfCondition.getPos(), script, object, true);
+                    }
+                }
+                if (testOK) {
+                    node.append(elseIfTemplates[i].evaluate(object, mode));
+                }
+            }
+            if (!testOK) {
+                node.append(elseTemplate.evaluate(object, mode));
+            }
+        }
+        return node;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        String optElse = elseTemplate.toString();
+        if (optElse.length() > 0) {
+            optElse = TemplateConstants.IF_ELSE + optElse;
+        }
+        final StringBuffer optElseIf = new StringBuffer(""); //$NON-NLS-1$
+        for (int i = 0; i < elseIfConditions.length; i++) {
+            optElseIf.append(TemplateConstants.IF_ELSE_IF);
+            optElseIf.append(elseIfConditions[i].toString());
+            optElseIf.append(TemplateConstants.IF_THEN);
+            optElseIf.append(elseIfTemplates[i].toString());
+        }
+        return TemplateConstants.IF_BEGIN + condition.toString() + TemplateConstants.IF_THEN + ifTemplate.toString() + optElseIf.toString() + optElse + TemplateConstants.IF_END;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String getOutlineText() {
+        return "if " + condition.toString(); //$NON-NLS-1$
+    }
+
+    /**
+     * It checks the syntax and creates a statement for the given part of the
+     * text. The part of the text to be parsed is delimited by the given limits.
+     * 
+     * @param buffer
+     *            is the textual representation of the templates
+     * @param limits
+     *            delimits the part of the text to be parsed for this statement
+     * @param script
+     *            is the generator's configuration
+     * @return the new statement
+     * @throws TemplateSyntaxException
+     */
+    public static TemplateNodeElement fromString(String buffer, Int2 limits, IScript script) throws TemplateSyntaxException {
+        TemplateExpression condition;
+        Template ifTemplate;
+        final List elseIfConditions = new ArrayList();
+        final List elseIfTemplates = new ArrayList();
+        Template elseTemplate;
+        // If -> Then
+        final Int2 iThen = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_THEN, limits.b(), limits.e(), TemplateConstants.SPEC, TemplateConstants.INHIBS_EXPRESSION);
+        if (iThen.b() > -1) {
+            condition = TemplateExpression.fromString(buffer, new Int2(limits.b(), iThen.b()), script);
+            int iThenEnd;
+            // Else -> End
+            final Int2 iElse = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_ELSE, iThen.e(), limits.e(), null, TemplateConstants.INHIBS_STATEMENT);
+            if (iElse.b() > -1) {
+                iThenEnd = iElse.b();
+                Int2 elsePos = new Int2(iElse.e(), limits.e());
+                elsePos = Template.formatTemplate(buffer, elsePos, 0);
+                elseTemplate = Template.read(buffer, elsePos, script);
+            } else {
+                iThenEnd = limits.e();
+                elseTemplate = new Template(script);
+            }
+            // ElseIf -> ElseIf|Else|End
+            final int iElseIfEndMax = iThenEnd;
+            Int2 iElseIf = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_ELSE_IF, iThen.e(), iElseIfEndMax, null, TemplateConstants.INHIBS_STATEMENT);
+            if (iElseIf.b() > -1) {
+                iThenEnd = iElseIf.b();
+                while (iElseIf.b() > -1) {
+                    // ElseIf test
+                    TemplateExpression elseIfTest;
+                    final Int2 iTestEnd = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_THEN, iElseIf.e(), iElseIfEndMax, TemplateConstants.SPEC,
+                            TemplateConstants.INHIBS_EXPRESSION);
+                    if (iTestEnd.b() > -1) {
+                        elseIfTest = TemplateExpression.fromString(buffer, new Int2(iElseIf.e(), iTestEnd.b()), script);
+                    } else {
+                        throw new TemplateSyntaxException(AcceleoGenMessages.getString("TemplateSyntaxError.MissingCloseIf"), script, new Int2(iElseIf.e(), iElseIfEndMax)); //$NON-NLS-1$
+                    }
+                    iElseIf = TextSearch.getDefaultSearch().indexIn(buffer, TemplateConstants.IF_ELSE_IF, iTestEnd.e(), iElseIfEndMax, null, TemplateConstants.INHIBS_STATEMENT);
+                    Int2 elseIfPos;
+                    if (iElseIf.b() > -1) {
+                        elseIfPos = new Int2(iTestEnd.e(), iElseIf.b());
+                    } else {
+                        elseIfPos = new Int2(iTestEnd.e(), iElseIfEndMax);
+                    }
+                    elseIfPos = Template.formatTemplate(buffer, elseIfPos, 0);
+                    final Template elseIfTemplate = Template.read(buffer, elseIfPos, script);
+                    elseIfConditions.add(elseIfTest);
+                    elseIfTemplates.add(elseIfTemplate);
+                }
+            }
+            // Then -> ElseIf|Else|End
+            Int2 ifPos = new Int2(iThen.e(), iThenEnd);
+            ifPos = Template.formatTemplate(buffer, ifPos, 0);
+            ifTemplate = Template.read(buffer, ifPos, script);
+        } else {
+            condition = TemplateExpression.fromString(buffer, new Int2(limits.b(), limits.e()), script);
+            ifTemplate = new Template(script);
+            elseTemplate = new Template(script);
+        }
+        final TemplateIfStatement element = new TemplateIfStatement(condition, ifTemplate, (TemplateExpression[]) elseIfConditions.toArray(new TemplateExpression[elseIfConditions.size()]),
+                (Template[]) elseIfTemplates.toArray(new Template[elseIfTemplates.size()]), elseTemplate, script);
+        element.setPos(limits);
+        return element;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/AcceleoToolsMessages.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/AcceleoToolsMessages.java
new file mode 100644
index 0000000..8a6d3ff
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/AcceleoToolsMessages.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.query.legacy.tools;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class to access externalized Strings for Acceleo's tools.
+ * 
+ */
+public final class AcceleoToolsMessages {
+    /** Full qualified path to the properties file in which to seek the keys. */
+    private static final String BUNDLE_NAME = "org.eclipse.sirius.query.legacy.tools.acceleotoolsmessages"; //$NON-NLS-1$
+
+    /** Contains the locale specific {@link String}s needed by this plug-in. */
+    private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(AcceleoToolsMessages.BUNDLE_NAME);
+
+    /**
+     * Utility classes don't need to (and shouldn't) be instantiated.
+     */
+    private AcceleoToolsMessages() {
+        // prevents instantiation
+    }
+
+    /**
+     * Returns a specified {@link String} from the resource bundle.
+     * 
+     * @param key
+     *            Key of the String we seek.
+     * @return The String from the resource bundle associated with
+     *         <code>key</code>.
+     */
+    public static String getString(String key) {
+        try {
+            return AcceleoToolsMessages.getString(key, new Object[] {});
+        } catch (MissingResourceException e) {
+            return '!' + key + '!';
+        }
+    }
+
+    /**
+     * Returns a String from the resource bundle binded with the given
+     * arguments.
+     * 
+     * @param key
+     *            Key of the String we seek.
+     * @param arguments
+     *            Arguments for the String formatting.
+     * @return formatted {@link String}.
+     * @see MessageFormat#format(String, Object[])
+     */
+    public static String getString(String key, Object[] arguments) {
+        if (arguments == null) {
+            return MessageFormat.format(AcceleoToolsMessages.RESOURCE_BUNDLE.getString(key), new Object[] {});
+        }
+        return MessageFormat.format(AcceleoToolsMessages.RESOURCE_BUNDLE.getString(key), arguments);
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/AcceleoToolsPlugin.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/AcceleoToolsPlugin.java
new file mode 100644
index 0000000..6f5077c
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/AcceleoToolsPlugin.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.runtime.IStatus;
+import org.osgi.framework.BundleContext;
+
+import org.eclipse.sirius.query.legacy.tools.resources.AcceleoPlugin;
+
+/**
+ * The main plugin class to be used in the desktop.
+ * 
+ * 
+ */
+public class AcceleoToolsPlugin extends AcceleoPlugin {
+
+    /* (non-Javadoc) */
+    @Override
+    public String getID() {
+        return "org.eclipse.sirius.query.legacy.tools"; //$NON-NLS-1$
+    }
+
+    /**
+     * The shared instance.
+     */
+    private static AcceleoToolsPlugin plugin;
+
+    /**
+     * Resource bundle.
+     */
+    private ResourceBundle resourceBundle;
+
+    /**
+     * Acceleo log errors count.
+     */
+    private int errorsCount = 0;
+
+    /**
+     * Acceleo log warnings count.
+     */
+    private int warningsCount = 0;
+
+    /**
+     * The constructor.
+     */
+    public AcceleoToolsPlugin() {
+        super();
+        AcceleoToolsPlugin.plugin = this;
+    }
+
+    /**
+     * Returns the Acceleo log count.
+     * 
+     * @param lowestSeverity
+     *            is the lowest severity (IStatus.ERROR, IStatus.WARNING)
+     * @return the Acceleo log count
+     */
+    public int getAcceleoLogCount(int lowestSeverity) {
+        if (lowestSeverity == IStatus.ERROR) {
+            return errorsCount;
+        } else if (lowestSeverity == IStatus.WARNING) {
+            return warningsCount + errorsCount;
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * Adds an Acceleo log.
+     * 
+     * @param status
+     *            is the status of the log
+     */
+    public void newAcceleoLog(IStatus status) {
+        if (status.getSeverity() == IStatus.ERROR) {
+            errorsCount++;
+        } else if (status.getSeverity() == IStatus.WARNING) {
+            warningsCount++;
+        }
+    }
+
+    /**
+     * Adds a warning.
+     */
+    public void newWarning() {
+        warningsCount++;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public void start(BundleContext context) throws Exception {
+        super.start(context);
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        super.stop(context);
+        AcceleoToolsPlugin.plugin = null;
+        resourceBundle = null;
+    }
+
+    /**
+     * @return the shared instance
+     */
+    public static AcceleoToolsPlugin getDefault() {
+        return AcceleoToolsPlugin.plugin;
+    }
+
+    /**
+     * Returns the string from the plugin's resource bundle, or 'key' if not
+     * found.
+     * 
+     * @param key
+     *            identifies the string
+     * @return the string from the plugin's resource bundle, or 'key' if not
+     *         found
+     */
+    public static String getResourceString(String key) {
+        ResourceBundle bundle = AcceleoToolsPlugin.getDefault().getResourceBundle();
+        try {
+            return (bundle != null) ? bundle.getString(key) : key;
+        } catch (MissingResourceException e) {
+            return key;
+        }
+    }
+
+    /**
+     * Returns the plugin's resource bundle.
+     * 
+     * @return the plugin's resource bundle
+     */
+    public ResourceBundle getResourceBundle() {
+        try {
+            if (resourceBundle == null) {
+                resourceBundle = ResourceBundle.getBundle("org.eclipse.sirius.query.legacy.tools.AcceleoToolsPluginResources"); //$NON-NLS-1$
+            }
+        } catch (MissingResourceException x) {
+            resourceBundle = null;
+        }
+        return resourceBundle;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/acceleotoolsmessages.properties b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/acceleotoolsmessages.properties
new file mode 100644
index 0000000..285fe5c
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/acceleotoolsmessages.properties
@@ -0,0 +1,32 @@
+#===============================================================================
+# Copyright (c) 2005-2014 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:
+#    Obeo - initial API and implementation
+#===============================================================================
+## NOTE TO TRANSLATORS : apostrophes (') need to be doubled if you need one displayed
+## org.eclipse.sirius.query.legacy.tools.log
+AcceleoConsole.Title = Acceleo Console
+
+## org.eclipse.sirius.query.legacy.tools.resources
+AcceleoPlugin.UnknownError = Unknown Acceleo problem
+AcceleoPlugin.MissingElement = Required element not found
+AcceleoPlugin.UnexpectedException = A java exception has been thrown
+
+JarFactory.InterruptedAction = Operation interrupted
+JarFactory.CreationFailed = Jar file couldn't be created : {0}
+
+Resources.InvalidContainer = The container {0} already exists and isn't a folder
+Resources.MissingContainer = The container {0} does not exist in the root container
+Resources.FileCreationFailed = The file {0} could not be created
+Resources.FileCreationFailedInRoot = The file {0} could not be created in the root container
+Resources.MissingProject = The project {0} doesn't exist in the root container
+Resources.EmptyPath = Path should be specified
+
+## org.eclipse.sirius.query.legacy.tools.strings
+TextSearch.CharacterLineNotFound = The line corresponding to the character {0} cannot be found in the file {1}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoClassLoader.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoClassLoader.java
new file mode 100644
index 0000000..ee36e9f
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoClassLoader.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.classloaders;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.emf.ecore.EObject;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+/**
+ * A class loader that combines plugins, acceleo services, and metamodels.
+ * 
+ */
+public class AcceleoClassLoader extends URLClassLoader {
+
+    /**
+     * The preferred class loader.
+     */
+    protected static ClassLoader preferredClassLoader = null;
+
+    /**
+     * The preferred class loader cache class name -> Class.
+     */
+    protected static Map preferedCache = new HashMap();
+
+    /**
+     * Updates the preferred class loader with the given model object.
+     * 
+     * @param object
+     *            is the model object
+     */
+    public static void setPreferredLoader(EObject object) {
+        if (object != null) {
+            ClassLoader loader = object.getClass().getClassLoader();
+            if (AcceleoClassLoader.preferredClassLoader != loader) {
+                AcceleoClassLoader.preferedCache = new HashMap();
+            }
+            AcceleoClassLoader.preferredClassLoader = loader;
+        } else {
+            AcceleoClassLoader.preferedCache = new HashMap();
+            AcceleoClassLoader.preferredClassLoader = null;
+        }
+    }
+
+    /**
+     * @param loader
+     *            is the preferred class loader
+     */
+    public static void setPreferredClassLoader(ClassLoader loader) {
+        if (AcceleoClassLoader.preferredClassLoader != loader) {
+            AcceleoClassLoader.preferedCache = new HashMap();
+        }
+        AcceleoClassLoader.preferredClassLoader = loader;
+    }
+
+    /**
+     * @return the preferred class loader
+     */
+    public static ClassLoader getPreferredClassLoader() {
+        return AcceleoClassLoader.preferredClassLoader;
+    }
+
+    /**
+     * The optional bundle that contains the classes.
+     */
+    private Bundle bundle;
+
+    /**
+     * Constructor.
+     * 
+     * @param urls
+     *            are the specific URLs of the classloader
+     * @param parent
+     *            is the parent classloader
+     */
+    public AcceleoClassLoader(URL[] urls, ClassLoader parent) {
+        super(urls, parent);
+        this.bundle = null;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param bundle
+     *            is the optional bundle that contains the generator
+     * @param parent
+     *            is the parent classloader
+     */
+    public AcceleoClassLoader(Bundle bundle, ClassLoader parent) {
+        super(new URL[] {}, parent);
+        this.bundle = bundle;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public Class loadClass(String name) throws ClassNotFoundException {
+        try {
+            if (bundle != null) {
+                Class c = loadClassInBundle(bundle, name, true);
+                if (c != null) {
+                    return c;
+                } else {
+                    return loadClassInPreferredLoader(name);
+                }
+            } else {
+                return loadClassInPreferredLoader(name);
+            }
+        } catch (ClassNotFoundException e) {
+            return loadClassInPreferredLoader(name);
+        } catch (NoClassDefFoundError e) {
+            return loadClassInPreferredLoader(name);
+        }
+    }
+
+    private Class loadClassInBundle(Bundle bundle, String name, boolean requiredSearch) {
+        try {
+            return bundle.loadClass(name);
+        } catch (ClassNotFoundException e) {
+            if (requiredSearch) {
+                return loadClassInRequiredBundles(bundle, name);
+            }
+        } catch (NoClassDefFoundError e) {
+            if (requiredSearch) {
+                return loadClassInRequiredBundles(bundle, name);
+            }
+        }
+        return null;
+    }
+
+    private Class loadClassInRequiredBundles(Bundle bundle, String name) {
+        String requiredBundles = bundle.getHeaders().get(Constants.REQUIRE_BUNDLE);
+        if (requiredBundles != null) {
+            StringTokenizer st = new StringTokenizer(requiredBundles, ","); //$NON-NLS-1$
+            while (st.hasMoreTokens()) {
+                String id = st.nextToken().trim();
+                int iDot = id.indexOf(';');
+                if (iDot > -1) {
+                    id = id.substring(0, iDot).trim();
+                }
+                if (id.length() > 0) {
+                    Bundle requiredBundle = Platform.getBundle(id);
+                    if (requiredBundle != null) {
+                        Class c = loadClassInBundle(requiredBundle, name, false);
+                        if (c != null) {
+                            return c;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private Class loadClassInPreferredLoader(String name) throws ClassNotFoundException {
+        Class res = (Class) AcceleoClassLoader.preferedCache.get(name);
+
+        if (res == null) {
+            try {
+                if (AcceleoClassLoader.preferredClassLoader != null && AcceleoClassLoader.preferredClassLoader != this && AcceleoClassLoader.preferredClassLoader != getParent()) {
+                    res = AcceleoClassLoader.preferredClassLoader.loadClass(name);
+                }
+            } catch (ClassNotFoundException e) {
+                // continue
+            } catch (NoClassDefFoundError e) {
+                // continue
+            }
+            if (res == null) {
+                try {
+                    res = getParent().loadClass(name);
+                } catch (ClassNotFoundException e) {
+                    res = super.loadClass(name);
+                } catch (NoClassDefFoundError e) {
+                    res = super.loadClass(name);
+                }
+            }
+            if (res != null) {
+                AcceleoClassLoader.preferedCache.put(name, res);
+            }
+        }
+        return res;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoGenClassLoader.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoGenClassLoader.java
new file mode 100644
index 0000000..ffbdda6
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoGenClassLoader.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.classloaders;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+/**
+ * This is a classloader for a generator project.
+ * 
+ */
+public class AcceleoGenClassLoader extends AcceleoClassLoader {
+
+    /**
+     * Cache File -> URLs.
+     */
+    private static Map cacheURL = new HashMap();
+
+    /**
+     * Constructor.
+     * 
+     * @param project
+     *            is the project that contains the generator
+     * @param parent
+     *            is the parent classloader
+     */
+    public AcceleoGenClassLoader(IProject project, ClassLoader parent) {
+        super(AcceleoGenClassLoader.computeURLs(project), parent);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param bundle
+     *            is the bundle that contains the generator
+     * @param parent
+     *            is the parent classloader
+     */
+    public AcceleoGenClassLoader(Bundle bundle, ClassLoader parent) {
+        super(bundle, parent);
+    }
+
+    private static URL[] computeURLs(IProject project) {
+        List list = new ArrayList();
+        AcceleoGenClassLoader.computeURLs(project, list);
+        return (URL[]) list.toArray(new URL[list.size()]);
+    }
+
+    private static void computeURLs(IProject project, List URLs) {
+        IFolder binFolder = Resources.getOutputFolder(project);
+        if (binFolder != null) {
+            String location = binFolder.getLocation().toString();
+            if (location.startsWith("/")) { //$NON-NLS-1$
+                location = '/' + location;
+            }
+            try {
+                URLs.add(new URL("file:/" + location + '/')); //$NON-NLS-1$
+            } catch (MalformedURLException e) {
+                // continue
+            }
+        }
+        IJavaProject javaProject = JavaCore.create(project);
+        IClasspathEntry[] entries;
+        try {
+            entries = javaProject.getResolvedClasspath(true);
+        } catch (JavaModelException e1) {
+            entries = new IClasspathEntry[] {};
+        }
+        for (IClasspathEntry entry : entries) {
+            if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+                IProject reference = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().toString());
+                if (reference.exists()) {
+                    AcceleoGenClassLoader.computeURLs(reference, URLs);
+                }
+            } else if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+                try {
+                    IFile reference = ResourcesPlugin.getWorkspace().getRoot().getFile(entry.getPath());
+                    if (reference.exists()) {
+                        URL url = (URL) AcceleoGenClassLoader.cacheURL.get(reference.getLocation().toFile());
+                        if (url == null) {
+                            url = reference.getLocation().toFile().toURL();
+                            AcceleoGenClassLoader.cacheURL.put(reference.getLocation().toFile(), url);
+                        }
+                        URLs.add(url);
+                    } else {
+                        URL url = (URL) AcceleoGenClassLoader.cacheURL.get(entry.getPath().toFile());
+                        if (url == null) {
+                            url = entry.getPath().toFile().toURL();
+                            AcceleoGenClassLoader.cacheURL.put(entry.getPath().toFile(), url);
+                        }
+                        URLs.add(url);
+                    }
+                } catch (MalformedURLException e) {
+                    // continue
+                }
+            } else {
+                try {
+                    URL url = (URL) AcceleoGenClassLoader.cacheURL.get(entry.getPath().toFile());
+                    if (url == null) {
+                        url = entry.getPath().toFile().toURL();
+                        AcceleoGenClassLoader.cacheURL.put(entry.getPath().toFile(), url);
+                    }
+                    URLs.add(url);
+                } catch (MalformedURLException e) {
+                    // continue
+                }
+            }
+        }
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoMetaClassLoader.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoMetaClassLoader.java
new file mode 100644
index 0000000..6916435
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/classloaders/AcceleoMetaClassLoader.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.classloaders;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.osgi.framework.Bundle;
+
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+/**
+ * This is a classloader for a metamodel project.
+ * 
+ */
+public class AcceleoMetaClassLoader extends AcceleoClassLoader {
+
+    /**
+     * Constructor.
+     * 
+     * @param project
+     *            is the project that contains the code of the metamodel
+     * @param parent
+     *            is the parent classloader
+     */
+    public AcceleoMetaClassLoader(IProject project, ClassLoader parent) {
+        super(AcceleoMetaClassLoader.resource2URLs(project), parent);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param bundle
+     *            is the optional bundle that contains the generator
+     * @param parent
+     *            is the parent classloader
+     */
+    public AcceleoMetaClassLoader(Bundle bundle, ClassLoader parent) {
+        super(bundle, parent);
+    }
+
+    /**
+     * Gets the URLs of the project.
+     * 
+     * @param project
+     *            is the project
+     * @return the URLs of the project
+     */
+    private static URL[] resource2URLs(IProject project) {
+        try {
+            IFolder binFolder = Resources.getOutputFolder(project);
+            if (binFolder != null) {
+                String location = binFolder.getLocation().toString();
+                if (location.startsWith("/")) { //$NON-NLS-1$
+                    location = '/' + location;
+                }
+                return new URL[] { new URL("file:/" + location + '/') }; //$NON-NLS-1$
+            } else {
+                return new URL[] {};
+            }
+        } catch (MalformedURLException e) {
+            return new URL[] {};
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/format/Conventions.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/format/Conventions.java
new file mode 100644
index 0000000..427dc22
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/format/Conventions.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.format;
+
+/**
+ * Conventions to format text.
+ * 
+ * 
+ */
+public class Conventions {
+
+    /**
+     * Transforms a multiline text into a literal.
+     * 
+     * @param value
+     *            is the multiline text
+     * @return the literal (single line)
+     */
+    public static String formatString(String value) {
+        StringBuffer result = new StringBuffer();
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            switch (c) {
+            case '\t':
+                result.append("\\t"); //$NON-NLS-1$
+                break;
+            case '\n':
+                result.append("\\n"); //$NON-NLS-1$
+                break;
+            case '\r':
+                result.append("\\r"); //$NON-NLS-1$
+                break;
+            case '\"':
+                result.append("\\\""); //$NON-NLS-1$
+                break;
+            case '\\':
+                result.append("\\\\"); //$NON-NLS-1$
+                break;
+            default:
+                result.append(c);
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * Transforms a literal into a multiline text.
+     * 
+     * @param value
+     *            is the literal (single line)
+     * @return the multiline text
+     */
+    public static String unformatString(String value) {
+        StringBuffer result = new StringBuffer();
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            if (c == '\\' && i + 1 < value.length()) {
+                i++;
+                c = value.charAt(i);
+                switch (c) {
+                case 't':
+                    result.append('\t');
+                    break;
+                case 'n':
+                    result.append('\n');
+                    break;
+                case 'r':
+                    result.append('\r');
+                    break;
+                case '"':
+                    result.append('"');
+                    break;
+                case '\\':
+                    result.append('\\');
+                    break;
+                default:
+                    result.append('\\');
+                    result.append(c);
+                }
+            } else {
+                result.append(c);
+            }
+        }
+        return result.toString();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/AcceleoException.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/AcceleoException.java
new file mode 100644
index 0000000..ad388fe
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/AcceleoException.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.log;
+
+/**
+ * Acceleo Exception.
+ * 
+ * 
+ */
+public class AcceleoException extends Exception {
+
+    private static final long serialVersionUID = 1;
+
+    /**
+     * Constructor.
+     */
+    public AcceleoException() {
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param message
+     *            is the message
+     */
+    public AcceleoException(String message) {
+        super(message);
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/IFailure.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/IFailure.java
new file mode 100644
index 0000000..c0323a7
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/IFailure.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.log;
+
+/**
+ * This is a failure for a TreeLog.
+ * <p>
+ * It's about an error having a message and a position.
+ * 
+ * 
+ */
+public interface IFailure {
+
+    /**
+     * @return the failure message
+     */
+    public String getMessage();
+
+    /**
+     * @return the position in the text
+     */
+    public int position();
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/Trace.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/Trace.java
new file mode 100644
index 0000000..2671821
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/Trace.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.log;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.eclipse.sirius.query.legacy.tools.format.Conventions;
+
+/**
+ * Trace for the acceleo tools.
+ * 
+ * 
+ */
+public class Trace {
+
+    /**
+     * Puts in a string the stack trace of an exception.
+     * 
+     * @param e
+     *            is an exception
+     * @return the stack transformed into a string
+     */
+    public static String getStackTrace(Throwable e) {
+        Writer result = new StringWriter();
+        PrintWriter printWriter = new PrintWriter(result);
+        e.printStackTrace(printWriter);
+        return result.toString();
+    }
+
+    /**
+     * It Indicates if trace is done.
+     * <p>
+     * It prints messages in the console.
+     */
+    public static boolean TRACE = false;
+
+    /**
+     * It prints the given text in the console.
+     * 
+     * @param text
+     *            is the message to print
+     */
+    public static void console(String text) {
+        if (Trace.TRACE) {
+            text = Conventions.formatString(text);
+            System.out.println(Trace.tabs() + text);
+        }
+    }
+
+    /**
+     * It computes correct indentation.
+     */
+    protected static String tabs() {
+        String tabs = ""; //$NON-NLS-1$
+        for (int i = 0; i < Trace.nbTab; i++) {
+            tabs += "  "; //$NON-NLS-1$
+        }
+        return tabs;
+    }
+
+    /**
+     * It adds a tabulation for the indentation.
+     */
+    public static void tab() {
+        Trace.nbTab++;
+    }
+
+    /**
+     * It withdraws a tabulation for the indentation.
+     */
+    public static void untab() {
+        if (Trace.nbTab > 0) {
+            Trace.nbTab--;
+        }
+    }
+
+    /**
+     * Counts the tabulations in the indentation.
+     */
+    protected static int nbTab = 0;
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/TreeLog.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/TreeLog.java
new file mode 100644
index 0000000..8683809
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/log/TreeLog.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.log;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+/**
+ * This is a result log with a value, errors, and warnings.
+ * 
+ * 
+ */
+public abstract class TreeLog {
+
+    /**
+     * The value transmitted from a node to another.
+     */
+    protected Object value = null;
+
+    /**
+     * Constructor.
+     */
+    protected TreeLog() {
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param value
+     *            is the value transmitted from a node to another
+     */
+    protected TreeLog(Object value) {
+        this.value = value;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param failure
+     *            is the first failure
+     */
+    protected TreeLog(IFailure failure) {
+        addError(failure);
+    }
+
+    /**
+     * @return the value transmitted from a node to another
+     */
+    public Object getValue() {
+        return value;
+    }
+
+    /**
+     * @param value
+     *            is the value transmitted from a node to another
+     */
+    public void setValue(Object value) {
+        this.value = value;
+    }
+
+    /**
+     * Adds the errors and warnings of the other log.
+     * 
+     * @param otherLog
+     *            is the other log
+     * @param errorsToSevereWarnings
+     *            indicates if the errors of the other log become warnings
+     */
+    public void getAll(TreeLog otherLog, boolean errorsToSevereWarnings) {
+        if (errorsToSevereWarnings) {
+            severeWarnings.addAll(otherLog.errors);
+        } else {
+            errors.addAll(otherLog.errors);
+        }
+        severeWarnings.addAll(otherLog.severeWarnings);
+    }
+
+    /**
+     * Indicates if log is valid.
+     * 
+     * @return true if log is valid
+     */
+    public boolean isOk() {
+        return !hasError();
+    }
+
+    /**
+     * Indicates if log has errors. The warnings are ignored.
+     * 
+     * @return true if log has errors
+     */
+    public boolean hasError() {
+        return (errors.size() > 0);
+    }
+
+    /**
+     * Indicates if log has warnings. The errors are ignored.
+     * 
+     * @return true if log has warnings
+     */
+    public boolean hasSevereWarning() {
+        return (severeWarnings.size() > 0);
+    }
+
+    /**
+     * The comparator used to order the sorted set of failures. It guarantees
+     * that the sorted set will be in ascending failure order, sorted according
+     * to the natural order of the failures (method position).
+     */
+    protected static Comparator failureComparator = new Comparator() {
+        public int compare(Object arg0, Object arg1) {
+            IFailure failure0 = ((IFailure) arg0);
+            IFailure failure1 = ((IFailure) arg1);
+            if (failure0.position() < failure1.position()) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }
+    };
+
+    /**
+     * The sorted set of errors.
+     */
+    protected TreeSet errors = new TreeSet(TreeLog.failureComparator);
+
+    /**
+     * Adds a new error.
+     * 
+     * @param failure
+     *            is the new error
+     */
+    protected void addError(IFailure failure) {
+        errors.add(failure);
+    }
+
+    /**
+     * Iterates on all errors.
+     * 
+     * @return an iterator on all errors
+     */
+    public Iterator allErrors() {
+        return errors.iterator();
+    }
+
+    /**
+     * Gets last error.
+     * 
+     * @return the last error
+     */
+    public IFailure lastError() {
+        if (errors.size() > 0) {
+            return (IFailure) errors.last();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * The sorted set of warnings.
+     */
+    protected TreeSet severeWarnings = new TreeSet(TreeLog.failureComparator);
+
+    /**
+     * Adds a new warning.
+     * 
+     * @param failure
+     *            is the new warning
+     */
+    protected void addSevereWarning(IFailure failure) {
+        severeWarnings.add(failure);
+    }
+
+    /**
+     * Iterates on all warnings.
+     * 
+     * @return an iterator on all warnings
+     */
+    public Iterator allSevereWarnings() {
+        return severeWarnings.iterator();
+    }
+
+    /**
+     * Iterates on all errors and warnings.
+     * 
+     * @return an iterator on all errors and warnings
+     */
+    public Iterator allOrderedErrorsAndSevereWarnings() {
+        TreeSet all = new TreeSet(TreeLog.failureComparator);
+        all.addAll(errors);
+        all.addAll(severeWarnings);
+        return all.iterator();
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        String message = ""; //$NON-NLS-1$
+        Iterator errors = allOrderedErrorsAndSevereWarnings();
+        while (errors.hasNext()) {
+            Object failure = errors.next();
+            message += failure.toString() + '\n';
+        }
+        return message;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/plugins/AcceleoMetamodelProvider.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/plugins/AcceleoMetamodelProvider.java
new file mode 100644
index 0000000..72d790b
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/plugins/AcceleoMetamodelProvider.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.plugins;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+/**
+ * To find a metamodel file in the workspace or in the plugins
+ * 
+ * 
+ */
+public class AcceleoMetamodelProvider {
+
+    /**
+     * Gets the sole instance.
+     * 
+     * @return the sole instance
+     */
+    public static AcceleoMetamodelProvider getDefault() {
+        if (AcceleoMetamodelProvider.instance == null) {
+            AcceleoMetamodelProvider.instance = new AcceleoMetamodelProvider();
+        }
+        return AcceleoMetamodelProvider.instance;
+    }
+
+    /**
+     * The sole instance.
+     */
+    private static AcceleoMetamodelProvider instance;
+
+    /**
+     * Saves the plugin for each file.
+     */
+    private Map file2plugin = new HashMap();
+
+    /**
+     * Gets the identifier of the plugin that contains the given file.
+     * 
+     * @param file
+     *            is the file
+     * @return the plugin ID
+     */
+    public String getPluginId(File file) {
+        return (String) file2plugin.get(file);
+    }
+
+    /**
+     * Gets the file for the given full path in the workspace or in the plugins.
+     * 
+     * @param fullPath
+     *            is the full path of the file
+     * @return the file
+     */
+    public File getFile(IPath fullPath) {
+        if (fullPath != null && fullPath.segmentCount() > 0) {
+            IFile file = Resources.findFile(fullPath);
+            if (file != null) {
+                return file.getLocation().toFile();
+            } else {
+                String pluginId = fullPath.segment(0);
+                return getFile(pluginId, fullPath.removeFirstSegments(1)); // remove
+                // '/Project'
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the file for the relative path in the given plugin.
+     * 
+     * @param pluginId
+     *            is the plugin
+     * @param relativePath
+     *            is the relative path in the plugin
+     * @return the file
+     */
+    public File getFile(String pluginId, IPath relativePath) {
+        return getFile(pluginId, relativePath, true);
+    }
+
+    /**
+     * Gets the file for the relative path in the given plugin.
+     * 
+     * @param pluginId
+     *            is the plugin
+     * @param relativePath
+     *            is the relative path in the plugin
+     * @param requiredSearch
+     *            true to search in the required bundles
+     * @return the file
+     */
+    private File getFile(String pluginId, IPath relativePath, boolean requiredSearch) {
+        if (pluginId.indexOf("org.eclipse.") > -1) { // faster //$NON-NLS-1$
+            return null;
+        }
+        Bundle bundle = Platform.getBundle(pluginId);
+        if (bundle != null) {
+            URL url = bundle.getEntry(relativePath.toString());
+            if (url != null) {
+                File file = new File(Resources.transformToAbsolutePath(url));
+                if (file.exists()) {
+                    if (!file2plugin.containsKey(file)) {
+                        file2plugin.put(file, pluginId);
+                        // Copy the sibling in the bundle area
+                        Enumeration all = bundle.findEntries(relativePath.removeLastSegments(1).toString(), "*", false); //$NON-NLS-1$
+                        while (all != null && all.hasMoreElements()) {
+                            URL fileURL = (URL) all.nextElement();
+                            if (fileURL != null) {
+                                File ecoreFile = new File(Resources.transformToAbsolutePath(fileURL));
+                                if (ecoreFile.exists()) {
+                                    file2plugin.put(ecoreFile, pluginId);
+                                }
+                            }
+                        }
+                    }
+                    return file;
+                }
+            }
+            if (requiredSearch) {
+                String requiredBundles = bundle.getHeaders().get(Constants.REQUIRE_BUNDLE);
+                if (requiredBundles != null) {
+                    StringTokenizer st = new StringTokenizer(requiredBundles, ","); //$NON-NLS-1$
+                    while (st.hasMoreTokens()) {
+                        String id = st.nextToken().trim();
+                        int iDot = id.indexOf(';');
+                        if (iDot > -1) {
+                            id = id.substring(0, iDot).trim();
+                        }
+                        if (id.length() > 0) {
+                            File scriptFile = getFile(id, relativePath, false);
+                            if (scriptFile != null) {
+                                return scriptFile;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/plugins/AcceleoModuleProvider.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/plugins/AcceleoModuleProvider.java
new file mode 100644
index 0000000..4e062f7
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/plugins/AcceleoModuleProvider.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.plugins;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+/**
+ * To find a module file in the workspace or in the plugins
+ * 
+ * 
+ */
+public class AcceleoModuleProvider {
+
+    /**
+     * Gets the sole instance.
+     * 
+     * @return the sole instance
+     */
+    public static AcceleoModuleProvider getDefault() {
+        if (AcceleoModuleProvider.instance == null) {
+            AcceleoModuleProvider.instance = new AcceleoModuleProvider();
+        }
+        return AcceleoModuleProvider.instance;
+    }
+
+    /**
+     * The sole instance.
+     */
+    public final static File NOT_FOUND = new File("");
+
+    /**
+     * The sole instance.
+     */
+    private static AcceleoModuleProvider instance;
+
+    /**
+     * Saves the plugin for each file.
+     */
+    private Map file2plugin = new HashMap();
+
+    /**
+     * Saves the relative path for each file.
+     */
+    private Map file2relativePath = new HashMap();
+
+    /**
+     * Saves the file for each absolute path.
+     */
+    private Map absolutPath2file = new HashMap();
+
+    /**
+     * Gets the identifier of the plugin that contains the given file.
+     * 
+     * @param file
+     *            is the file
+     * @return the plugin ID
+     */
+    public String getPluginId(File file) {
+        return (String) file2plugin.get(file);
+    }
+
+    /**
+     * Gets the relative path of the given file.
+     * 
+     * @param file
+     *            is the file
+     * @return the relative path
+     */
+    public String getRelativePath(File file) {
+        return (String) file2relativePath.get(file);
+    }
+
+    /**
+     * Gets the file for the full name in the given plugin.
+     * 
+     * @param pluginId
+     *            is the plugin
+     * @param fullName
+     *            is the full name of the resource in the plugin
+     * @param extension
+     *            is the extension of the file to search
+     * @return the file
+     */
+    public File getFile(String pluginId, String fullName, String extension) {
+        IPath fullPath = new Path(fullName.replaceAll("\\.", "/")).addFileExtension(extension); //$NON-NLS-1$ //$NON-NLS-2$
+        return getFile(pluginId, fullPath);
+    }
+
+    /**
+     * Gets the file for the given full path in the workspace or in the plugins.
+     * 
+     * @param fullPath
+     *            is the full path of the file
+     * @return the file
+     */
+    public File getFile(IPath fullPath) {
+        if (fullPath != null && fullPath.segmentCount() > 0) {
+            IFile file = Resources.findFile(fullPath);
+            if (file != null) {
+                return file.getLocation().toFile();
+            } else {
+                String pluginId = fullPath.segment(0);
+                return getFile(pluginId, fullPath.removeFirstSegments(1)); // remove
+                // '/Project'
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the file for the relative path in the given plugin.
+     * 
+     * @param pluginId
+     *            is the plugin
+     * @param relativePath
+     *            is the relative path in the plugin
+     * @return the file
+     */
+    public File getFile(String pluginId, IPath relativePath) {
+        return getFile(pluginId, relativePath, true);
+    }
+
+    /**
+     * Gets the file for the relative path in the given plugin.
+     * 
+     * @param pluginId
+     *            is the plugin
+     * @param relativePath
+     *            is the relative path in the plugin
+     * @param requiredSearch
+     *            true to search in the required bundles
+     * @return the file
+     */
+    private File getFile(String pluginId, IPath relativePath, boolean requiredSearch) {
+        File res = null;
+        /*
+         * FIXME and Analyze if it is needed or if it impact performance in the
+         * Sirius case. if (pluginId.indexOf("org.eclipse.") <= -1) { // faster
+         * //$NON-NLS-1$
+         */
+        File cachedRes = (File) absolutPath2file.get(pluginId + relativePath);
+        if (cachedRes != null) {
+            if (cachedRes != AcceleoModuleProvider.NOT_FOUND) {
+                res = cachedRes;
+            }
+        } else {
+            Bundle bundle = Platform.getBundle(pluginId);
+            if (bundle != null) {
+                URL url = bundle.getEntry(relativePath.toString());
+                if (url == null && "mt".equals(relativePath.getFileExtension()) && relativePath.segmentCount() > 1) { //$NON-NLS-1$
+                    url = bundle.getEntry(relativePath.removeFirstSegments(1).toString());
+                    if (url == null) {
+                        url = getRuntimeModeURL(bundle, relativePath);
+                    }
+                }
+                if (url != null) {
+                    File file = new File(Resources.transformToAbsolutePath(url));
+                    if (file.exists()) {
+                        if (!file2plugin.containsKey(file)) {
+                            file2plugin.put(file, pluginId);
+                            file2relativePath.put(file, relativePath.toString());
+                            // Copy the properties in the bundle area
+                            Enumeration allProperties = bundle.findEntries(relativePath.removeLastSegments(1).toString(), "*.properties", true); //$NON-NLS-1$
+                            while (allProperties != null && allProperties.hasMoreElements()) {
+                                URL propertyFileURL = (URL) allProperties.nextElement();
+                                if (propertyFileURL != null) {
+                                    File propertyFile = new File(Resources.transformToAbsolutePath(propertyFileURL));
+                                    if (propertyFile.exists()) {
+                                        file2plugin.put(propertyFile, pluginId);
+                                    }
+                                }
+                            }
+                        }
+                        res = file;
+                    }
+                } else {
+                    if (requiredSearch) {
+                        String requiredBundles = bundle.getHeaders().get(Constants.REQUIRE_BUNDLE);
+                        if (requiredBundles != null) {
+                            StringTokenizer st = new StringTokenizer(requiredBundles, ","); //$NON-NLS-1$
+                            while (st.hasMoreTokens()) {
+                                String id = st.nextToken().trim();
+                                int iDot = id.indexOf(';');
+                                if (iDot > -1) {
+                                    id = id.substring(0, iDot).trim();
+                                }
+                                if (id.length() > 0) {
+                                    File scriptFile = getFile(id, relativePath, true);
+                                    if (scriptFile != null) {
+                                        res = scriptFile;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (res != null) {
+                absolutPath2file.put(pluginId + relativePath, res);
+            } else {
+                absolutPath2file.put(pluginId + relativePath, AcceleoModuleProvider.NOT_FOUND);
+            }
+        }
+        /*
+         * }
+         */
+        return res;
+    }
+
+    private URL getRuntimeModeURL(Bundle bundle, IPath relativePath) {
+        Map mtName2mtURLs = (Map) bundleName2mtPaths.get(bundle.getSymbolicName());
+        if (mtName2mtURLs == null) {
+            mtName2mtURLs = new HashMap();
+            bundleName2mtPaths.put(bundle.getSymbolicName(), mtName2mtURLs);
+            Enumeration entries = bundle.findEntries("/", "*.mt", true); //$NON-NLS-1$ //$NON-NLS-2$
+            if (entries != null) {
+                while (entries.hasMoreElements()) {
+                    URL entry = (URL) entries.nextElement();
+                    if (entry != null) {
+                        IPath path = new Path(entry.getPath());
+                        if (path.segmentCount() > 0) {
+                            String name = path.lastSegment();
+                            List mt = (List) mtName2mtURLs.get(name);
+                            if (mt == null) {
+                                mt = new ArrayList();
+                                mtName2mtURLs.put(name, mt);
+                            }
+                            mt.add(entry);
+                        }
+                    }
+                }
+            }
+        }
+        List URLs = (List) mtName2mtURLs.get(relativePath.lastSegment());
+        if (URLs != null) {
+            Iterator it = URLs.iterator();
+            while (it.hasNext()) {
+                URL url = (URL) it.next();
+                if (url.getPath().indexOf(relativePath.toString()) > -1) {
+                    return url;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Map bundleName2mtPaths = new HashMap();
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/AcceleoPlugin.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/AcceleoPlugin.java
new file mode 100644
index 0000000..3668a39
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/AcceleoPlugin.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.query.legacy.tools.resources;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+import org.eclipse.sirius.query.legacy.tools.AcceleoToolsMessages;
+import org.eclipse.sirius.query.legacy.tools.AcceleoToolsPlugin;
+import org.eclipse.sirius.query.legacy.tools.log.AcceleoException;
+
+/**
+ * Abstract acceleo plugin class (not UI). All plugins extend this class that
+ * contains ID and log facilities.
+ */
+public abstract class AcceleoPlugin extends Plugin {
+
+    /**
+     * @return the identifier of the plugin
+     */
+    public abstract String getID();
+
+    /**
+     * Puts the given status in the error log view.
+     * 
+     * @param status
+     *            is the status
+     */
+    public void log(IStatus status) {
+        getLog().log(status);
+        AcceleoToolsPlugin.getDefault().newAcceleoLog(status);
+    }
+
+    /**
+     * Puts the given exception in the error log view, as error or warning.
+     * 
+     * @param e
+     *            is the exception to put in the error log view
+     * @param blocker
+     *            is the severity : (blocker)? IStatus.ERROR : IStatus.WARNING
+     */
+    public void log(Throwable e, boolean blocker) {
+        if (e instanceof CoreException) {
+            IStatus status = ((CoreException) e).getStatus();
+            log(new Status(status.getSeverity(), getID(), status.getCode(), status.getMessage(), status.getException()));
+        } else if (e instanceof InvocationTargetException) {
+            log(((InvocationTargetException) e).getTargetException(), blocker);
+        } else if (e instanceof AcceleoException) {
+            int severity = (blocker) ? IStatus.ERROR : IStatus.WARNING;
+            log(new Status(severity, getID(), severity, ((e.getMessage() != null) ? e.getMessage() : AcceleoToolsMessages.getString("AcceleoPlugin.UnknownError")), null)); //$NON-NLS-1$
+        } else if (e instanceof NullPointerException) {
+            int severity = (blocker) ? IStatus.ERROR : IStatus.WARNING;
+            log(new Status(severity, getID(), severity, AcceleoToolsMessages.getString("AcceleoPlugin.MissingElement"), e)); //$NON-NLS-1$
+        } else {
+            int severity = (blocker) ? IStatus.ERROR : IStatus.WARNING;
+            log(new Status(severity, getID(), severity, AcceleoToolsMessages.getString("AcceleoPlugin.UnexpectedException"), e)); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Puts the given message in the error log view, as error or warning.
+     * 
+     * @param message
+     *            is the message to put in the error log view
+     * @param blocker
+     *            is the severity : (blocker)? IStatus.ERROR : IStatus.WARNING
+     */
+    public void log(String message, boolean blocker) {
+        int severity = (blocker) ? IStatus.ERROR : IStatus.WARNING;
+        log(new Status(severity, getID(), severity, ((message != null) ? message.trim().replaceFirst("\n", ";\n") : AcceleoToolsMessages.getString("AcceleoPlugin.UnknownError")), null)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/FileContentMap.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/FileContentMap.java
new file mode 100644
index 0000000..36e37ac
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/FileContentMap.java
@@ -0,0 +1,349 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.resources;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+
+/**
+ * Gets file's content more faster.
+ * 
+ * 
+ */
+public class FileContentMap {
+
+    /**
+     * The max capacity.
+     */
+    protected int max;
+
+    /**
+     * File to content mappings.
+     */
+    protected Map file2content;
+
+    /**
+     * File to modification stamp mappings.
+     */
+    protected Map file2OldModificationStamp = new HashMap();
+
+    /**
+     * Files priorities.
+     */
+    protected List priority = new ArrayList();
+
+    /**
+     * Constructor.
+     */
+    public FileContentMap() {
+        this(-1, true);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param max
+     *            is the max capacity
+     */
+    public FileContentMap(int max) {
+        this(max, true);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param weak
+     *            to use weak hashmap
+     */
+    public FileContentMap(boolean weak) {
+        this(-1, weak);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param max
+     *            is the max capacity
+     * @param weak
+     *            to use weak hashmap
+     */
+    public FileContentMap(int max, boolean weak) {
+        this.max = max;
+        if (weak) {
+            file2content = new WeakHashMap();
+        } else {
+            file2content = new HashMap();
+        }
+    }
+
+    /**
+     * Returns the value to which the specified file is mapped in this identity
+     * map, or null if the map contains no mapping for this file, or null if the
+     * file has been modified.
+     * 
+     * @param file
+     *            is the file
+     * @return the value to which the specified file is mapped
+     */
+    public Object get(IFile file) {
+        if (file != null) {
+            String path = file.getFullPath().toString();
+            Object content = file2content.get(path);
+            Double newModificationStamp = new Double(file.getModificationStamp() + file.getLocalTimeStamp());
+            Double oldModificationStamp = (Double) file2OldModificationStamp.get(path);
+            if (content != null && oldModificationStamp != null && oldModificationStamp.doubleValue() == newModificationStamp.doubleValue()) {
+                if (content instanceof EObject) {
+                    return getForEObject((EObject) content);
+                } else {
+                    return content;
+                }
+            } else {
+                // Remove the expired element
+                file2content.remove(path);
+                file2OldModificationStamp.remove(path);
+                priority.remove(path);
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value to which the specified file is mapped in this identity
+     * map, or null if the map contains no mapping for this file, or null if the
+     * file has been modified.
+     * 
+     * @param file
+     *            is the file
+     * @return the value to which the specified file is mapped
+     */
+    public Object get(File file) {
+        if (file != null) {
+            String path = file.getAbsolutePath().toString();
+            IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(path));
+            if (workspaceFile != null && workspaceFile.isAccessible()) {
+                return get(workspaceFile);
+            } else {
+                Object content = file2content.get(path);
+                Double newModificationStamp = new Double(file.lastModified());
+                Double oldModificationStamp = (Double) file2OldModificationStamp.get(path);
+                if (content != null && oldModificationStamp != null && oldModificationStamp.doubleValue() == newModificationStamp.doubleValue()) {
+                    if (content instanceof EObject) {
+                        return getForEObject((EObject) content);
+                    } else {
+                        return content;
+                    }
+                } else {
+                    // Remove the expired element
+                    file2content.remove(path);
+                    file2OldModificationStamp.remove(path);
+                    priority.remove(path);
+                    return null;
+                }
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private EObject getForEObject(EObject content) {
+        if (content.eResource() != null && content.eResource().getResourceSet() != null) {
+            ResourceSet resourceSet = content.eResource().getResourceSet();
+            Iterator resources = resourceSet.getResources().iterator();
+            while (resources.hasNext()) {
+                Resource resource = (Resource) resources.next();
+                if (resource != content.eResource() && resource.getURI() != null) {
+                    IFile loadedFile = Resources.getIFile(resource.getURI());
+                    if (loadedFile != null && loadedFile.exists()) {
+                        Double newModificationStamp = new Double(loadedFile.getModificationStamp() + loadedFile.getLocalTimeStamp());
+                        Double oldModificationStamp = (Double) file2OldModificationStamp.get(loadedFile.getFullPath().toString());
+                        if (oldModificationStamp == null || oldModificationStamp.doubleValue() != newModificationStamp.doubleValue()) {
+                            return null;
+                        }
+                    }
+                }
+            }
+        }
+        return content;
+    }
+
+    /**
+     * Associates the specified value with the specified key in this map. If the
+     * map previously contained a mapping for this key, the old value is
+     * replaced.
+     * 
+     * @param file
+     *            is the file
+     * @param content
+     *            is the value to which the specified file is mapped
+     */
+    public void put(IFile file, Object content) {
+        if (file != null) {
+            String path = file.getFullPath().toString();
+            if (max > -1 && size() >= max && priority.size() > 0) {
+                // Remove the oldest element
+                Object toRemove = priority.get(0);
+                file2content.remove(toRemove);
+                file2OldModificationStamp.remove(toRemove);
+                priority.remove(0);
+            }
+            file2content.put(path, content);
+            file2OldModificationStamp.put(path, new Double(file.getModificationStamp() + file.getLocalTimeStamp()));
+            if (content instanceof EObject) {
+                putForEObject((EObject) content);
+            }
+            priority.add(path);
+        }
+    }
+
+    /**
+     * Associates the specified value with the specified key in this map. If the
+     * map previously contained a mapping for this key, the old value is
+     * replaced.
+     * 
+     * @param file
+     *            is the file
+     * @param content
+     *            is the value to which the specified file is mapped
+     */
+    public void put(File file, Object content) {
+        if (file != null) {
+            String path = file.getAbsolutePath().toString();
+            IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(path));
+            if (workspaceFile != null && workspaceFile.isAccessible()) {
+                put(workspaceFile, content);
+            } else {
+                if (max > -1 && size() >= max && priority.size() > 0) {
+                    // Remove the oldest element
+                    Object toRemove = priority.get(0);
+                    file2content.remove(toRemove);
+                    file2OldModificationStamp.remove(toRemove);
+                    priority.remove(0);
+                }
+                file2content.put(path, content);
+                file2OldModificationStamp.put(path, new Double(file.lastModified()));
+                if (content instanceof EObject) {
+                    putForEObject((EObject) content);
+                }
+                priority.add(path);
+            }
+        }
+    }
+
+    private void putForEObject(EObject content) {
+        if (content.eResource() != null && content.eResource().getResourceSet() != null) {
+            ResourceSet resourceSet = content.eResource().getResourceSet();
+            Iterator resources = resourceSet.getResources().iterator();
+            while (resources.hasNext()) {
+                Resource resource = (Resource) resources.next();
+                if (resource != content.eResource() && resource.getURI() != null) {
+                    IFile loadedFile = Resources.getIFile(resource.getURI());
+                    if (loadedFile != null && loadedFile.exists()) {
+                        file2OldModificationStamp.put(loadedFile.getFullPath().toString(), new Double(loadedFile.getModificationStamp() + loadedFile.getLocalTimeStamp()));
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes the element for the given file.
+     * 
+     * @param file
+     *            is the file
+     */
+    public void remove(IFile file) {
+        String path = file.getFullPath().toString();
+        file2content.remove(path);
+        file2OldModificationStamp.remove(path);
+        priority.remove(path);
+    }
+
+    /**
+     * Removes the element for the given file.
+     * 
+     * @param file
+     *            is the file
+     */
+    public void remove(File file) {
+        String path = file.getAbsolutePath().toString();
+        IFile workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(path));
+        if (workspaceFile != null && workspaceFile.isAccessible()) {
+            remove(workspaceFile);
+        } else {
+            file2content.remove(path);
+            file2OldModificationStamp.remove(path);
+            priority.remove(path);
+        }
+    }
+
+    /**
+     * Returns the number of key-value mappings in this map.
+     * 
+     * @return the number of key-value mappings in this map
+     */
+    public int size() {
+        return file2content.size();
+    }
+
+    /**
+     * Removes all elements.
+     */
+    public void clear() {
+        file2content.clear();
+        file2OldModificationStamp.clear();
+        priority.clear();
+    }
+
+    /**
+     * Returns a collection view of the values contained in this map.
+     * <p>
+     * For (weak == false) only.
+     * <p>
+     * 
+     * @return a collection view of the values contained in this map
+     */
+    public Collection values() {
+        if (!(file2content instanceof WeakHashMap)) {
+            return file2content.values();
+        } else {
+            return new ArrayList();
+        }
+    }
+
+    /**
+     * Returns a set view of the entries contained in this map.
+     * <p>
+     * 
+     * @return a set of the entries contained in this map
+     */
+    public Set entrySet() {
+        return file2content.entrySet();
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/Resources.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/Resources.java
new file mode 100644
index 0000000..c36400d
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/Resources.java
@@ -0,0 +1,788 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.resources;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.osgi.framework.Constants;
+
+import org.eclipse.sirius.query.legacy.tools.AcceleoToolsPlugin;
+
+/**
+ * It helps to use workspace resources.
+ * 
+ */
+public class Resources {
+
+    private static final String INSTALL_LOCATION_TAG = "INSTALL_LOCATION"; //$NON-NLS-1$
+
+    private static final String WORKSPACE_LOCATION_TAG = "WORKSPACE_LOCATION"; //$NON-NLS-1$
+
+    private static final int BOM_SIZE = 3;
+
+    /**
+     * Returns the content of the file.
+     * 
+     * @param file
+     *            is the file
+     * @return the content of the file, or an empty buffer if the file doesn't
+     *         exist
+     */
+    public static StringBuffer getFileContent(IFile file) {
+        return Resources.getFileContent(file, true);
+    }
+
+    /**
+     * Returns the content of the file.
+     * 
+     * @param file
+     *            is the file
+     * @param report
+     *            indicates if an error is reported when the file doesn't exist
+     * @return the content of the file, or an empty buffer if the file doesn't
+     *         exist
+     */
+    public static StringBuffer getFileContent(IFile file, boolean report) {
+        StringBuffer buffer = Resources.doGetFileContent(file, report);
+        if (file != null && Resources.isTemplateFile(file.getName()) && Resources.getEncoding(buffer) != null) {
+            buffer = Resources.getEncodedFileContent(file, report, Resources.getEncoding(buffer));
+        }
+        return buffer;
+    }
+
+    /**
+     * Returns the content of the file.
+     * 
+     * @param file
+     *            is the file
+     * @param report
+     *            indicates if an error is reported when the file doesn't exist
+     * @return the content of the file, or an empty buffer if the file doesn't
+     *         exist
+     */
+    private static StringBuffer doGetFileContent(IFile file, boolean report) {
+        StringBuffer buffer = new StringBuffer();
+        if (file != null) {
+
+            UnicodeBOMInputStream ubis = null;
+            InputStream content = null;
+            try {
+                content = file.getContents(false);
+                ubis = new UnicodeBOMInputStream(content);
+                ubis.skipBOM();
+                byte[] readBuffer = new byte[ubis.available()];
+                int n = ubis.read(readBuffer);
+                while (n > 0) {
+                    buffer.append(new String(readBuffer));
+                    n = ubis.read(readBuffer);
+                }
+            } catch (Exception e) {
+                if (report) {
+                    AcceleoToolsPlugin.getDefault().log(e, true);
+                }
+            } finally {
+                if (ubis != null) {
+                    try {
+                        ubis.close();
+                    } catch (IOException e) {
+                        if (report) {
+                            AcceleoToolsPlugin.getDefault().log(e, true);
+                        }
+                    }
+                }
+                if (content != null) {
+                    try {
+                        content.close();
+                    } catch (IOException e) {
+                        if (report) {
+                            AcceleoToolsPlugin.getDefault().log(e, true);
+                        }
+                    }
+                }
+            }
+        }
+        return buffer;
+    }
+
+    /**
+     * Returns the content of the file.
+     * 
+     * @param file
+     *            is the file
+     * @return the content of the file, or an empty buffer if the file doesn't
+     *         exist
+     */
+    public static StringBuffer getFileContent(File file) {
+        return Resources.getFileContent(file, true);
+    }
+
+    /**
+     * Returns the content of the file.
+     * 
+     * @param file
+     *            is the file
+     * @param report
+     *            indicates if an error is reported when the file doesn't exist
+     * @return the content of the file, or an empty buffer if the file doesn't
+     *         exist
+     */
+    public static StringBuffer getFileContent(File file, boolean report) {
+        StringBuffer buffer = Resources.doGetFileContent(file, report);
+        String encoding = Resources.getEncoding(buffer);
+        if (file != null && Resources.isTemplateFile(file.getName()) && encoding != null) {
+            buffer = Resources.getEncodedFileContent(file, report, encoding);
+        }
+        return buffer;
+    }
+
+    /**
+     * @param file
+     *            any file (existing or not).
+     * @return true if this file is an Acceleo Template file, false otherwise.
+     */
+    private static boolean isTemplateFile(String filename) {
+        if (filename != null) {
+            if (filename.toLowerCase().endsWith("mt")) { //$NON-NLS-1$
+                return true;
+            }
+            if (filename.toLowerCase().endsWith("tr")) { //$NON-NLS-1$
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return the content of an {@link IFile} using the specified encoding.
+     * 
+     * @param file
+     *            file to read.
+     * @param report
+     *            if it's set to true, any error will get reported, otherwise
+     *            some errors may appear silently.
+     * @param encodingCode
+     *            encodingCode to use in order to read the file.
+     * @return an unicode {@link StringBuffer} of the file content.
+     */
+    public static StringBuffer getEncodedFileContent(File file, boolean report, String encodingCode) {
+        StringBuffer buffer = new StringBuffer();
+        FileInputStream fiss;
+        UnicodeBOMInputStream fis;
+        try {
+            fiss = new FileInputStream(file);
+            fis = new UnicodeBOMInputStream(fiss);
+            fis.skipBOM();
+            InputStreamReader in = new InputStreamReader(fis, encodingCode);
+            try {
+                char[] buff = new char[512];
+                int size = in.read(buff);
+                while (size > 0) {
+                    buffer.append(buff, 0, size);
+                    size = in.read(buff);
+                }
+            } finally {
+                if (in != null) {
+                    in.close();
+                }
+                if (fiss != null) {
+                    fiss.close();
+                }
+                if (fis != null) {
+                    fis.close();
+                }
+            }
+        } catch (IOException e) {
+            if (report && !(e instanceof UnsupportedEncodingException)) {
+                AcceleoToolsPlugin.getDefault().log(e, true);
+            }
+        }
+
+        return buffer;
+    }
+
+    /**
+     * Return the content of an {@link IFile} using the specified encoding.
+     * 
+     * @param file
+     *            file to read.
+     * @param report
+     *            if it's set to true, any error will get reported, otherwise
+     *            some errors may appear silently.
+     * @param encodingCode
+     *            encodingCode to use in order to read the file.
+     * @return an unicode {@link StringBuffer} of the file content.
+     */
+    public static StringBuffer getEncodedFileContent(IFile file, boolean report, String encodingCode) {
+        StringBuffer buffer = new StringBuffer();
+        if (file != null) {
+            UnicodeBOMInputStream content = null;
+            try {
+                content = new UnicodeBOMInputStream(file.getContents(false));
+                content.skipBOM();
+                /*
+                 * create an InputStreamReader specifying an encoding.
+                 */
+                InputStreamReader in = new InputStreamReader(content, encodingCode);
+                try {
+                    char[] buff = new char[content.available()];
+                    int size = in.read(buff);
+                    while (size > 0) {
+                        buffer.append(buff, 0, size);
+                        size = in.read(buff);
+                    }
+                } finally {
+                    if (in != null) {
+                        in.close();
+                    }
+                }
+            } catch (Exception e) {
+                if (report) {
+                    AcceleoToolsPlugin.getDefault().log(e, true);
+                }
+            } finally {
+                if (content != null) {
+                    try {
+                        content.close();
+                    } catch (IOException e) {
+                        if (report && !(e instanceof UnsupportedEncodingException)) {
+                            AcceleoToolsPlugin.getDefault().log(e, true);
+                        }
+                    }
+                }
+            }
+        }
+        return buffer;
+    }
+
+    /**
+     * Returns the content of the file.
+     * 
+     * @param file
+     *            is the file
+     * @param report
+     *            indicates if an error is reported when the file doesn't exist
+     * @return the content of the file, or an empty buffer if the file doesn't
+     *         exist
+     */
+    private static StringBuffer doGetFileContent(File file, boolean report) {
+        StringBuffer buffer = new StringBuffer();
+        try {
+            FileInputStream fis = new FileInputStream(file);
+            UnicodeBOMInputStream ubis = new UnicodeBOMInputStream(fis);
+            ubis.skipBOM();
+            BufferedReader in = new BufferedReader(new InputStreamReader(ubis));
+            try {
+                char[] buff = new char[512];
+                int size = in.read(buff);
+                while (size > 0) {
+                    buffer.append(buff, 0, size);
+                    size = in.read(buff);
+                }
+            } finally {
+                if (in != null) {
+                    in.close();
+                }
+                if (fis != null) {
+                    fis.close();
+                }
+                if (ubis != null) {
+                    ubis.close();
+                }
+            }
+        } catch (IOException e) {
+            if (report) {
+                AcceleoToolsPlugin.getDefault().log(e, true);
+            }
+        }
+        return buffer;
+    }
+
+    /**
+     * Gets the default output of the project.
+     * 
+     * @param project
+     *            is the project
+     * @return the default output of the project, or null if it doesn't exist
+     */
+    public static IFolder getOutputFolder(IProject project) {
+        final IJavaProject projet = JavaCore.create(project);
+        try {
+            IPath output = projet.getOutputLocation();
+            if (output != null && output.segmentCount() > 1) {
+                IFolder folder = project.getWorkspace().getRoot().getFolder(output);
+                if (folder.exists()) {
+                    return folder;
+                } else {
+                    return null;
+                }
+            } else {
+                return null;
+            }
+        } catch (JavaModelException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Creates and load a persistent EMF document for a resource in the
+     * workspace.
+     * 
+     * @param resource
+     *            is the resource in the workspace
+     * @param load
+     *            indicates if the persistent EMF document is loaded
+     * @return the persistent EMF document
+     */
+    public static Resource getResource(IResource resource, boolean load) {
+        ResourceSetImpl resourceSet = new ResourceSetImpl();
+        Resource result = resourceSet.getResource(Resources.createPlatformResourceURI(resource.getFullPath().toString()), load);
+        // EcoreUtil.resolveAll(resourceSet);
+        return result;
+    }
+
+    /**
+     * Gets the resource in the workspace for a persistent EMF document.
+     * 
+     * @param resource
+     *            is the persistent EMF document
+     * @return the resource in the workspace
+     */
+    public static IFile getIFile(Resource resource) {
+        URI uri = resource.getURI();
+        if ("cdo".equals(uri.scheme())) { //$NON-NLS-1$
+            if (resource.getURI().path() != null) {
+                if (resource.getURI().path() != null) {
+                    IPath path = Path.fromPortableString(resource.getURI().path());
+                    IContainer folder = (IContainer) ResourcesPlugin.getWorkspace().getRoot().findMember(path.removeLastSegments(1));
+                    if (folder != null) {
+                        path = path.removeFirstSegments(path.segmentCount() - 1);
+                        if ("system".equals(path.getFileExtension())) { //$NON-NLS-1$
+                            path = path.removeFileExtension().removeFileExtension().addFileExtension("system").addFileExtension("ost"); //$NON-NLS-1$ //$NON-NLS-2$
+                        } else if ("xmi".equals(path.getFileExtension())) { //$NON-NLS-1$
+                            path = path.removeFileExtension().addFileExtension("ost"); //$NON-NLS-1$
+                        }
+                        return folder.getFile(path);
+                    }
+                }
+            }
+        } else {
+            String path = uri.path();
+            if (path != null) {
+                if (path.startsWith("/resource")) { //$NON-NLS-1$
+                    path = path.substring("/resource".length()); //$NON-NLS-1$
+                }
+                IResource member = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
+                if (member instanceof IFile) {
+                    return (IFile) member;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Finds and returns the member resource identified by the given path in the
+     * workspace, or null if no such resource exists.
+     * 
+     * @param path
+     *            is the path of the desired resource
+     * @return the member resource, or null if no such resource exists
+     */
+    public static IResource findResource(IPath path) {
+        IWorkspace workspace = ResourcesPlugin.getWorkspace();
+        if (workspace.getRoot().exists(path)) {
+            return workspace.getRoot().findMember(path);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Finds and returns the file identified by the given path in the workspace,
+     * or null if no such file exists.
+     * 
+     * @param path
+     *            is the path of the desired resource
+     * @return the member file, or null if no such resource exists
+     */
+    public static IFile findFile(IPath path) {
+        IResource resource = Resources.findResource(path);
+        if (resource instanceof IFile) {
+            return (IFile) resource;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Creates a platform-relative path URI.
+     * 
+     * @param path
+     *            is the path of the URI to create
+     * @return the new URI
+     * @see org.eclipse.emf.common.util.URI#createPlatformResourceURI
+     */
+    public static URI createPlatformResourceURI(String path) {
+        if (path.startsWith("platform:/plugin")) { //$NON-NLS-1$
+            return URI.createURI(path, true);
+        } else {
+            return URI.createPlatformResourceURI(path, true);
+        }
+    }
+
+    /**
+     * Creates relative path from absolute. Resolve relative pathnames against
+     * workspace directory.
+     * 
+     * @param absolutePath
+     *            absolute file path (directory or file).
+     * @return relative path if workspace directory is included in absolutePath,
+     *         otherwise return absolute path.
+     */
+    public static String makeWorkspaceRelativePath(String absolutePath) {
+        return Resources.makeRelativePath(ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString(), absolutePath);
+    }
+
+    /**
+     * Creates relative path from absolute. Resolve relative pathnames against
+     * parent directory.
+     * 
+     * @param parentPath
+     *            parent directory path.
+     * @param absolutePath
+     *            absolute file path (directory or file).
+     * @return relative path if parent directory is included in absolutePath,
+     *         otherwise return absolute path.
+     */
+    public static String makeRelativePath(String parentPath, String absolutePath) {
+        String relativePath = null;
+        if (parentPath != null && absolutePath != null && parentPath.length() < absolutePath.length()) {
+            File absoluteFile = new File(absolutePath);
+            if (absoluteFile.isAbsolute()) {
+                File parentFile = new File(parentPath);
+                if (parentFile.isAbsolute()) {
+                    String dirPath = parentFile.getAbsolutePath().replace('\\', '/');
+                    absolutePath = absolutePath.replace('\\', '/');
+                    int dirLength = dirPath.length();
+                    if (absolutePath.substring(0, dirLength).equalsIgnoreCase(dirPath)) {
+                        relativePath = absolutePath.substring(dirLength);
+                        if (relativePath.startsWith("/")) { //$NON-NLS-1$
+                            relativePath = relativePath.substring(1);
+                        }
+                    }
+                } else {
+                    relativePath = absoluteFile.getPath().replace('\\', '/');
+                }
+            } else {
+                relativePath = absoluteFile.getPath().replace('\\', '/');
+            }
+        } else {
+            if (absolutePath != null) {
+                relativePath = absolutePath.replace('\\', '/');
+            }
+        }
+        return relativePath;
+    }
+
+    /**
+     * Creates the absolute path.
+     * 
+     * @param url
+     *            is the relative path
+     * @return the absolute file path
+     */
+    public static String transformToAbsolutePath(URL url) {
+        String absolutePath;
+        try {
+            URL transformedUrl = FileLocator.toFileURL(url);
+            File file = new File(transformedUrl.getFile());
+            absolutePath = file.getAbsolutePath();
+        } catch (IOException e) {
+            absolutePath = ""; //$NON-NLS-1$
+            AcceleoToolsPlugin.getDefault().log(e, true);
+        }
+        return absolutePath;
+    }
+
+    /**
+     * Get the IFile for the URI.
+     * 
+     * @param uri
+     *            is the URI
+     * @return the IFile if the URI is a project form, or null if not a project
+     *         form, OR the project doesn't exist.The IFile returned doesn't
+     *         necessarily exist.
+     */
+    public static IFile getIFile(URI uri) {
+        IProject project = Resources.getProject(uri);
+        if (project != null) {
+            IPath path;
+            if (Resources.isPlatformResourceURI(uri)) {
+                // remove /resource/project name/
+                path = new Path(URI.decode(uri.path())).removeFirstSegments(2);
+            } else {
+                // remove /project name/
+                path = new Path(URI.decode(uri.path())).removeFirstSegments(1);
+            }
+            return project.getFile(path);
+        } else {
+            return null;
+        }
+    }
+
+    private static IProject getProject(URI uri) {
+        String projectName;
+        if (Resources.isPlatformResourceURI(uri)) {
+            projectName = uri.segment(1);
+        } else if (uri.scheme() == null) {
+            projectName = new Path(uri.path()).segment(0); // project name is
+            // first in the URI
+        } else {
+            return null;
+        }
+        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(URI.decode(projectName));
+        if (project != null && project.isAccessible()) {
+            return project;
+        } else {
+            return null;
+        }
+    }
+
+    private static boolean isPlatformResourceURI(URI uri) {
+        return "platform".equals(uri.scheme()) && "resource".equals(uri.segment(0)); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Gets the required plugins for the given project.
+     * 
+     * @param project
+     *            is the project
+     * @return the IDs of the required plugins
+     */
+    public static String[] getRequiredPluginIDs(IProject project) {
+        List IDs = new ArrayList();
+        IFile file = project.getFile(JarFile.MANIFEST_NAME);
+        Double cachedTimestamp = (Double) Resources.fileTimestamp.get(file);
+        if (cachedTimestamp != null && file.getModificationStamp() + file.getLocalTimeStamp() == cachedTimestamp.longValue()) {
+            IDs = (List) Resources.fileRequired.get(file);
+        } else {
+            if (file.exists()) {
+                InputStream manifestStream = null;
+                try {
+                    manifestStream = new FileInputStream(file.getLocation().toFile());
+                    Manifest manifest = new Manifest(manifestStream);
+                    Properties prop = Resources.manifestToProperties(manifest.getMainAttributes());
+                    String requiredBundles = (String) prop.get(Constants.REQUIRE_BUNDLE);
+                    if (requiredBundles != null) {
+                        StringTokenizer st = new StringTokenizer(requiredBundles, ","); //$NON-NLS-1$
+                        while (st.hasMoreTokens()) {
+                            String id = st.nextToken().trim();
+                            int iDot = id.indexOf(';');
+                            if (iDot > -1) {
+                                id = id.substring(0, iDot).trim();
+                            }
+                            if (id.length() > 0) {
+                                IDs.add(id);
+                            }
+                        }
+                    }
+                } catch (FileNotFoundException e) {
+                } catch (IOException e) {
+                } finally {
+                    try {
+                        if (manifestStream != null) {
+                            manifestStream.close();
+                        }
+                    } catch (IOException e) {
+                    }
+                }
+            }
+            Resources.fileTimestamp.put(file, new Double(file.getModificationStamp() + file.getLocalTimeStamp()));
+            Resources.fileRequired.put(file, IDs);
+        }
+        return (String[]) IDs.toArray(new String[IDs.size()]);
+    }
+
+    /**
+     * Cache map File -> time stamp.
+     */
+    private static Map fileTimestamp = new HashMap();
+
+    /**
+     * Cache file -> required plug-in.
+     */
+    private static Map fileRequired = new HashMap();
+
+    private static Properties manifestToProperties(Attributes d) {
+        Iterator iter = d.keySet().iterator();
+        Properties result = new Properties();
+        while (iter.hasNext()) {
+            Attributes.Name key = (Attributes.Name) iter.next();
+            result.put(key.toString(), d.get(key));
+        }
+        return result;
+    }
+
+    /**
+     * Decodes an acceleo path, it replaces the acceleo tags by the workspace
+     * location or the platform location.
+     * 
+     * @param path
+     *            is the path to decode
+     * @return the absolute path
+     * @see encodeAcceleoAbsolutePath
+     */
+    public static String decodeAcceleoAbsolutePath(String path) {
+        if (path == null) {
+            return path;
+        } else {
+            if (path.startsWith(Resources.WORKSPACE_LOCATION_TAG)) {
+                String workspaceLocation;
+                if (ResourcesPlugin.getWorkspace().getRoot().getLocation() != null) {
+                    workspaceLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
+                } else {
+                    workspaceLocation = ""; //$NON-NLS-1$
+                }
+                return workspaceLocation + path.substring(Resources.WORKSPACE_LOCATION_TAG.length());
+            } else if (path.startsWith(Resources.INSTALL_LOCATION_TAG)) {
+                String installLocation;
+                if (Platform.getInstallLocation() != null) {
+                    installLocation = new Path(Resources.transformToAbsolutePath(Platform.getInstallLocation().getURL())).toString();
+                } else {
+                    installLocation = ""; //$NON-NLS-1$
+                }
+                return installLocation + path.substring(Resources.INSTALL_LOCATION_TAG.length());
+            } else {
+                return path;
+            }
+        }
+    }
+
+    /**
+     * Encodes an absolute path, it replaces the workspace location or the
+     * platform location by an acceleo tag.
+     * 
+     * @param path
+     *            is the path to encode
+     * @return the acceleo path
+     * @see decodeAcceleoAbsolutePath
+     */
+    public static String encodeAcceleoAbsolutePath(String path) {
+        if (path == null) {
+            return path;
+        } else {
+            path = new Path(path).toString();
+            String workspaceLocation = null;
+            if (ResourcesPlugin.getWorkspace().getRoot().getLocation() != null) {
+                workspaceLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
+            }
+            if (workspaceLocation != null && path.startsWith(workspaceLocation)) {
+                return Resources.WORKSPACE_LOCATION_TAG + path.substring(workspaceLocation.length());
+            } else {
+                String installLocation = null;
+                if (Platform.getInstallLocation() != null) {
+                    installLocation = new Path(Resources.transformToAbsolutePath(Platform.getInstallLocation().getURL())).toString();
+                }
+                if (installLocation != null && path.startsWith(installLocation)) {
+                    return Resources.INSTALL_LOCATION_TAG + path.substring(installLocation.length());
+                } else {
+                    return path;
+                }
+            }
+        }
+    }
+
+    /**
+     * Encoding specification start marker, used in MT templates to indicate to
+     * Acceleo in which encoding the file should be loaded.
+     */
+    private static final String ENCODING_START = "encoding=";//$NON-NLS-1$
+
+    /**
+     * @param buffer
+     *            buffer in which we want to look for an encoding code.
+     * @return a {@link String} having an encoding code as value (be carefull it
+     *         may be a wrong code, you'll have to check by yourself). It may
+     *         return null if no encoding code is found.
+     */
+    public static String getEncoding(StringBuffer buffer) {
+        String startMarker = "<%--"; //$NON-NLS-1$
+        String endMarker = "--%>"; //$NON-NLS-1$
+        String result = Resources.doGetEncoding(buffer, startMarker, endMarker);
+        if (result == null) {
+            startMarker = "[%--"; //$NON-NLS-1$
+            endMarker = "--%]"; //$NON-NLS-1$
+            result = Resources.doGetEncoding(buffer, startMarker, endMarker);
+        }
+        return result;
+    }
+
+    /**
+     * Look for an encoding specification in a buffer using start and end
+     * markers.
+     * 
+     * @param buffer
+     *            buffer in which we want to look for an encoding code.
+     * @param startMarker
+     *            start marker of the language.
+     * @param endMarker
+     *            end marker of the language.
+     * @return the found encoding code or null.
+     */
+    private static String doGetEncoding(StringBuffer buffer, String startMarker, String endMarker) {
+        int start = buffer.indexOf(startMarker + Resources.ENCODING_START);
+        if (start != -1) {
+            int end = buffer.indexOf(endMarker, start);
+            if (end != -1) {
+                String encoding = buffer.substring(start + (startMarker + Resources.ENCODING_START).length(), end);
+                return encoding.trim().toUpperCase();
+            }
+        }
+        return null;
+    }
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/UnicodeBOMInputStream.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/UnicodeBOMInputStream.java
new file mode 100644
index 0000000..6c1e53e
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/resources/UnicodeBOMInputStream.java
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.sirius.query.legacy.tools.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+
+/**
+ * The <code>UnicodeBOMInputStream</code> class wraps any
+ * <code>InputStream</code> and detects the presence of any Unicode BOM (Byte
+ * Order Mark) at its beginning, as defined by <a
+ * href="http://www.faqs.org/rfcs/rfc3629.html">RFC 3629 - UTF-8, a
+ * transformation format of ISO 10646</a>
+ * 
+ * <p>
+ * The <a href="http://www.unicode.org/unicode/faq/utf_bom.html">Unicode FAQ</a>
+ * defines 5 types of BOMs:
+ * <ul>
+ * <li>
+ * 
+ * <pre>
+ * 00 00 FE FF  = UTF-32, big-endian
+ * </pre>
+ * 
+ * </li>
+ * <li>
+ * 
+ * <pre>
+ * FF FE 00 00  = UTF-32, little-endian
+ * </pre>
+ * 
+ * </li>
+ * <li>
+ * 
+ * <pre>
+ * FE FF        = UTF-16, big-endian
+ * </pre>
+ * 
+ * </li>
+ * <li>
+ * 
+ * <pre>
+ * FF FE        = UTF-16, little-endian
+ * </pre>
+ * 
+ * </li>
+ * <li>
+ * 
+ * <pre>
+ * EF BB BF     = UTF-8
+ * </pre>
+ * 
+ * </li>
+ * </ul>
+ * </p>
+ * 
+ * <p>
+ * Use the {@link #getBOM()} method to know whether a BOM has been detected or
+ * not.
+ * </p>
+ * <p>
+ * Use the {@link #skipBOM()} method to remove the detected BOM from the wrapped
+ * <code>InputStream</code> object.
+ * </p>
+ */
+public class UnicodeBOMInputStream extends InputStream {
+    /**
+     * Type safe enumeration class that describes the different types of Unicode
+     * BOMs.
+     */
+    public static final class BOM {
+        /**
+         * NONE.
+         */
+        public static final BOM NONE = new BOM(new byte[] {}, "NONE");
+
+        /**
+         * UTF-8 BOM (EF BB BF).
+         */
+        public static final BOM UTF_8 = new BOM(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }, "UTF-8");
+
+        /**
+         * UTF-16, little-endian (FF FE).
+         */
+        public static final BOM UTF_16_LE = new BOM(new byte[] { (byte) 0xFF, (byte) 0xFE }, "UTF-16 little-endian");
+
+        /**
+         * UTF-16, big-endian (FE FF).
+         */
+        public static final BOM UTF_16_BE = new BOM(new byte[] { (byte) 0xFE, (byte) 0xFF }, "UTF-16 big-endian");
+
+        /**
+         * UTF-32, little-endian (FF FE 00 00).
+         */
+        public static final BOM UTF_32_LE = new BOM(new byte[] { (byte) 0xFF, (byte) 0xFE, (byte) 0x00, (byte) 0x00 }, "UTF-32 little-endian");
+
+        /**
+         * UTF-32, big-endian (00 00 FE FF).
+         */
+        public static final BOM UTF_32_BE = new BOM(new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0xFE, (byte) 0xFF }, "UTF-32 big-endian");
+
+        /**
+         * Returns a <code>String</code> representation of this <code>BOM</code>
+         * value.
+         */
+        @Override
+        public final String toString() {
+            return description;
+        }
+
+        /**
+         * Returns the bytes corresponding to this <code>BOM</code> value.
+         */
+        public final byte[] getBytes() {
+            final int length = bytes.length;
+            final byte[] result = new byte[length];
+
+            // Make a defensive copy
+            System.arraycopy(bytes, 0, result, 0, length);
+
+            return result;
+        }
+
+        private BOM(final byte bom[], final String description) {
+            assert (bom != null) : "invalid BOM: null is not allowed";
+            assert (description != null) : "invalid description: null is not allowed";
+            assert (description.length() != 0) : "invalid description: empty string is not allowed";
+
+            this.bytes = bom;
+            this.description = description;
+        }
+
+        final byte bytes[];
+
+        private final String description;
+
+    } // BOM
+
+    /**
+     * Constructs a new <code>UnicodeBOMInputStream</code> that wraps the
+     * specified <code>InputStream</code>.
+     * 
+     * @param inputStream
+     *            an <code>InputStream</code>.
+     * 
+     * @throws NullPointerException
+     *             when <code>inputStream</code> is <code>null</code>.
+     * @throws IOException
+     *             on reading from the specified <code>InputStream</code> when
+     *             trying to detect the Unicode BOM.
+     */
+    public UnicodeBOMInputStream(final InputStream inputStream) throws NullPointerException, IOException
+
+    {
+        if (inputStream == null) {
+            throw new NullPointerException("invalid input stream: null is not allowed");
+        }
+
+        in = new PushbackInputStream(inputStream, 4);
+
+        final byte bom[] = new byte[4];
+        final int read = in.read(bom);
+
+        switch (read) {
+        case 4:
+            if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
+                this.bom = BOM.UTF_32_LE;
+                break;
+            } else if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
+                this.bom = BOM.UTF_32_BE;
+                break;
+            }
+
+        case 3:
+            if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
+                this.bom = BOM.UTF_8;
+                break;
+            }
+
+        case 2:
+            if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
+                this.bom = BOM.UTF_16_LE;
+                break;
+            } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
+                this.bom = BOM.UTF_16_BE;
+                break;
+            }
+
+        default:
+            this.bom = BOM.NONE;
+            break;
+        }
+
+        if (read > 0) {
+            in.unread(bom, 0, read);
+        }
+    }
+
+    /**
+     * Returns the <code>BOM</code> that was detected in the wrapped
+     * <code>InputStream</code> object.
+     * 
+     * @return a <code>BOM</code> value.
+     */
+    public final BOM getBOM() {
+        // BOM type is immutable.
+        return bom;
+    }
+
+    /**
+     * Skips the <code>BOM</code> that was found in the wrapped
+     * <code>InputStream</code> object.
+     * 
+     * @return this <code>UnicodeBOMInputStream</code>.
+     * 
+     * @throws IOException
+     *             when trying to skip the BOM from the wrapped
+     *             <code>InputStream</code> object.
+     */
+    public final synchronized UnicodeBOMInputStream skipBOM() throws IOException {
+        if (!skipped) {
+            in.skip(bom.bytes.length);
+            skipped = true;
+        }
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int read() throws IOException {
+        return in.read();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int read(final byte b[]) throws IOException, NullPointerException {
+        return in.read(b, 0, b.length);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int read(final byte b[], final int off, final int len) throws IOException, NullPointerException {
+        return in.read(b, off, len);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long skip(final long n) throws IOException {
+        return in.skip(n);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int available() throws IOException {
+        return in.available();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void close() throws IOException {
+        in.close();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public synchronized void mark(final int readlimit) {
+        in.mark(readlimit);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public synchronized void reset() throws IOException {
+        in.reset();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean markSupported() {
+        return in.markSupported();
+    }
+
+    private final PushbackInputStream in;
+
+    private final BOM bom;
+
+    private boolean skipped = false;
+
+} // UnicodeBOMInputStream
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/Int2.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/Int2.java
new file mode 100644
index 0000000..d3d437f
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/Int2.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.strings;
+
+/**
+ * Complex index in a string.
+ * <p>
+ * Attributes are public to simplify their uses.
+ * 
+ * 
+ */
+public class Int2 {
+
+    /**
+     * Index not found.
+     */
+    public static final Int2 NOT_FOUND = new Int2(-1, -1);
+
+    /**
+     * The begin index of a substring.
+     */
+    private int b;
+
+    /**
+     * The end index of a substring.
+     */
+    private int e;
+
+    /**
+     * Constructor.
+     * 
+     * @param b
+     *            is the begin index of a substring
+     * @param e
+     *            is the end index of a substring
+     */
+    public Int2(int b, int e) {
+        this.b = b;
+        this.e = e;
+    }
+
+    /**
+     * @return the begin index.
+     */
+    public int b() {
+        return b;
+    }
+
+    /**
+     * @return the end index.
+     */
+    public int e() {
+        return e;
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public boolean equals(Object arg0) {
+        if (arg0 instanceof Int2) {
+            Int2 other = (Int2) arg0;
+            return (b == other.b) && (e == other.e);
+        } else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public int hashCode() {
+        return b;
+    }
+
+    /**
+     * Shift bounds.
+     * 
+     * @param i
+     *            is the value to add
+     */
+    public void range(Int2 range) {
+        if (range.b > -1 && range.e > -1 && b > -1 && e > -1) {
+            if (e > range.e) {
+                e = range.e;
+            }
+            if (b < range.b) {
+                b = range.b;
+            }
+            if (b < e) {
+                b -= range.b;
+                e -= range.b;
+            } else {
+                b = -1;
+                e = -1;
+            }
+        } else {
+            b = -1;
+            e = -1;
+        }
+    }
+
+    /**
+     * Applies the indent strategy (each line adds one character).
+     * 
+     * @param lines
+     *            are the positions of the lines
+     */
+    public void indent(Int2[] lines) {
+        if (b > -1 && e > -1) {
+            int newB = b;
+            int newE = e;
+            for (Int2 line : lines) {
+                if (line.b() < b) {
+                    newB++;
+                }
+                if (line.b() < e) {
+                    newE++;
+                } else {
+                    break;
+                }
+            }
+            b = newB;
+            e = newE;
+        }
+    }
+
+    /* (non-Javadoc) */
+    @Override
+    public String toString() {
+        return '[' + Integer.toString(b) + ',' + Integer.toString(e) + ']';
+    }
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/Jump.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/Jump.java
new file mode 100644
index 0000000..181d6e3
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/Jump.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.strings;
+
+/**
+ * It's a scanner that ignores a sequence of characters.
+ * 
+ * 
+ */
+public interface Jump {
+
+    /**
+     * Returns the index within the buffer of the first occurrence of this jump,
+     * starting at the specified index.
+     * 
+     * @param buffer
+     *            is the text to be explored
+     * @param posBegin
+     *            is the beginning index
+     * @param posEnd
+     *            is the ending index
+     * @return the index within the buffer of the first occurrence
+     */
+    public Int2 begin(String buffer, int posBegin, int posEnd);
+
+    /**
+     * Returns the index within the buffer of the end of this jump.
+     * 
+     * @param buffer
+     *            is the text to be explored
+     * @param begin
+     *            is the beginning index of this jump
+     * @param posEnd
+     *            is the ending index
+     * @param spec
+     *            is the pattern's escape character
+     * @param inhibs
+     *            are the ignored blocks
+     * @return the last ignored index
+     */
+    public int end(String buffer, Int2 begin, int posEnd, String spec, String[][] inhibs);
+
+}
diff --git a/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/TextSearch.java b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/TextSearch.java
new file mode 100644
index 0000000..55bc5ca
--- /dev/null
+++ b/plugins/org.eclipse.sirius.query.legacy/src/org/eclipse/sirius/query/legacy/tools/strings/TextSearch.java
@@ -0,0 +1,989 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2014 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:
+ *    Obeo - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.sirius.query.legacy.tools.strings;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.eclipse.sirius.query.legacy.tools.AcceleoToolsMessages;
+import org.eclipse.sirius.query.legacy.tools.AcceleoToolsPlugin;
+import org.eclipse.sirius.query.legacy.tools.resources.FileContentMap;
+import org.eclipse.sirius.query.legacy.tools.resources.Resources;
+
+/**
+ * Java language supports pattern matching. This class includes methods for
+ * examining sequences of characters, for searching strings with or without the
+ * regular expression library. The public static attribute 'settings' specifies
+ * the pattern matching configuration for all the methods of this class : <li>
+ * regular expression</li> <li>ignore case</li> <li>escape characters</li> <li>
+ * recursive blocks</li>
+ * 
+ * 
+ */
+public class TextSearch {
+
+    /**
+     * This property is used to disable the blocks recursivity.
+     */
+    public static final String FORCE_NOT_RECURSIVE = "__FORCE_NOT_RECURSIVE__"; //$NON-NLS-1$
+
+    /**
+     * @return the default search
+     */
+    public static TextSearch getDefaultSearch() {
+        if (TextSearch.defaultSearch == null) {
+            TextSearch.defaultSearch = new TextSearch(false, false, true);
+        }
+        return TextSearch.defaultSearch;
+    }
+
+    private static TextSearch defaultSearch = null;
+
+    /**
+     * @return the regex search
+     */
+    public static TextSearch getRegexSearch() {
+        if (TextSearch.regexSearch == null) {
+            TextSearch.regexSearch = new TextSearch(true, false, true);
+        }
+        return TextSearch.regexSearch;
+    }
+
+    private static TextSearch regexSearch = null;
+
+    /**
+     * @return the ignore case search
+     */
+    public static TextSearch getIgnoreCaseSearch() {
+        if (TextSearch.ignoreCaseSearch == null) {
+            TextSearch.ignoreCaseSearch = new TextSearch(false, true, true);
+        }
+        return TextSearch.ignoreCaseSearch;
+    }
+
+    private static TextSearch ignoreCaseSearch = null;
+
+    /**
+     * The sequences of characters are read with (true) or without (false) the
+     * regular expression library.
+     */
+    private boolean regex;
+
+    /**
+     * Case is ignored if regex is false and IGNORE_CASE_IF_NOT_REGEX is true.
+     */
+    private boolean ignoreCase;
+
+    /**
+     * Blocks are recursively ignored.
+     * <p>
+     * Sample :
+     * <li>"{1 .. [2 .. {3 .. }4 .. ]5 .. }6" is the string to be parsed</li>
+     * <li>"[","]" and "{","}" are defined blocks</li>
+     * <li>if RECURSIVE_INHIBS is true then block {1 .. }6 is detected, else
+     * block {1 .. }4</li>
+     */
+    private boolean recursiveInhibs;
+
+    /**
+     * Constructor.
+     * 
+     * @param regex
+     *            indicates if the regular expression library is used
+     * @param ignoreCase
+     *            indicates if the case is ignored
+     * @param recursiveInhibs
+     *            indicates if the blocks are recursively ignored
+     */
+    private TextSearch(boolean regex, boolean ignoreCase, boolean recursiveInhibs) {
+        this.regex = regex;
+        this.ignoreCase = ignoreCase;
+        this.recursiveInhibs = recursiveInhibs;
+    }
+
+    /**
+     * Compiles the given regular expression into a pattern.
+     * 
+     * @param regex
+     *            is the expression to be compiled
+     * @return a compiled representation of a regular expression
+     * @throws PatternSyntaxException
+     *             if the expression's syntax is invalid
+     */
+    protected Pattern compile(String regex) {
+        Pattern pattern = (Pattern) patternMap.get(regex);
+        if (pattern == null) {
+            pattern = Pattern.compile(regex);
+            patternMap.put(regex, pattern);
+        }
+        return pattern;
+    }
+
+    private Map patternMap = new HashMap();
+
+    /**
+     * Indicates if the strings are matching.
+     * <p>
+     * The pattern matching configuration (Strings.settings) has to be verified
+     * before.
+     * 
+     * @param s1
+     *            is the first string
+     * @param s2
+     *            is the second string
+     * @return true if the strings are matching
+     */
+    public boolean matches(String s1, String s2) {
+        if (s1 == null && s2 == null) {
+            return true;
+        }
+        if (s1 == null || s2 == null) {
+            return false;
+        }
+        if (regex) {
+            Pattern pattern = compile(s2);
+            Matcher m = pattern.matcher(s1);
+            return m.matches();
+        } else {
+            if (ignoreCase) {
+                return s1.equalsIgnoreCase(s2);
+            } else {
+                return s1.equals(s2);
+            }
+        }
+    }
+
+    /**
+     * Returns the index within the buffer of the first occurrence of the
+     * specified substring.
+     * <p>
+     * The pattern matching configuration (Strings.settings) has to be verified
+     * before.
+     * 
+     * @param buffer
+     *            is the text to be explored
+     * @param tag
+     *            is the substring to search for
+     * @return The index within the buffer of the first occurrence of the
+     *         specified substring. If it does not occur as a substring,
+     *         Int2(-1,-1) is returned.
+     */
+    public Int2 indexOf(final String buffer, final String tag) {
+        return indexOf(buffer, tag, 0);
+    }
+
+    /**
+     * Returns the index within the buffer of the first occurrence of the
+     * specified substring, starting at the specified index. If no such
+     * substring occurs in this string at or after position pos, then
+     * Int2(-1,-1) is returned.
+     * <p>
+     * The pattern matching configuration (Strings.settings) has to be verified
+     * before.
+     * 
+     * @param buffer
+     *            is the text to be explored
+     * @param tag
+     *            is the substring to search for
+     * @param pos
+     *            is the index to start the search from
+     * @return The index within the buffer of the first occurrence of the
+     *         specified substring, starting at the specified index. If it does
+     *         not occur as a substring, or pos < 0, or buffer.length() <= pos,
+     *         Int2(-1,-1) is returned.
+     */
+    public Int2 indexOf(final String buffer, final String tag, int pos) {
+        return indexIn(buffer, tag, pos, buffer.length());
+    }
+
+    /**
+     * Returns the index within the buffer of the first occurrence of the
+     * specified substring. If no such substring occurs in this string, then
+     * Int2(-1,-1) is returned.
+     * 
+     * @param buffer
+     *            is the text to be explored
+     * @param tag
+     *            is the substring to search for
+     * @param spec
+     *            is the pattern's escape character
+     * @param inhibs
+     *            are the ignored sub-blocks
+     * @return the index within the buffer of the first occurrence of the
+     *         specified substring. If it does not occur as a substring,
+     *         Int2(-1,-1) is returned. It returns 0 if (tag.length() == 0).
+     */
+    public Int2 indexOf(final String buffer, final String tag, String spec, String[][] inhibs) {
+        return indexOf(buffer, tag, 0, spec, inhibs);
+    }
+
+    /**
+     * Returns the index within the buffer of the first occurrence of the
+     * specified substring, starting at the specified index. If no such
+     * substring occurs in this string at or after position pos, then
+     * Int2(-1,-1) is returned.
+     * <p>
+     * An inhibs element sample : String[] = { 1,2 (,3)? }
+     * <li>1:begin tag "</li>
+     * <li>2:end tag "</li>
+     * <li>3:blocks properties FORCE_NOT_RECURSIVE</li>
+     * 
+     * @param buffer
+     *            is the text to be explored
+     * @param tag
+     *            is the substring to search for
+     * @param pos
+     *            is the beginning index
+     * @param spec
+     *            is the pattern's escape character
+     * @param inhibs
+     *            are the ignored sub-blocks
+     * @return the index within the buffer of the first occurrence of the
+     *         specified substring, starting at the specified index. If it does
+     *         not occur as a substring, or pos < 0, or buffer.length() <= pos,
+     *         Int2(-1,-1) is returned. It returns 0 if (tag.length() == 0).
+     */
+    public Int2 indexOf(final String buffer, final String tag, int pos, String spec, String[][] inhibs) {
+        return indexOf(buffer, tag, pos, spec, null, inhibs);
+    }
+
+    /**
+     * Returns the index within the buffer of the first occurrence of the
+     * specified substring, starting at the specified index. If no such
+     * substring occurs in this string at or after position pos, then
+     * Int2(-1,-1) is returned.
+     * <p>
+     * An inhibs element sample : String[] = { 1,2 (,3)? }
+     * <li>1:begin tag "</li>
+     * <li>2:end tag "</li>
+     * <li>3:blocks properties FORCE_NOT_RECURSIVE</li>
+     * 
+     * @param buffer
+     *            is the text to be explored
+     * @param tag
+     *            is the substring to search for
+     * @param pos
+     *            is the beginning index
+     * @param spec
+     *            is the pattern's escape character
+     * @param jump
+     *            is a scanner that ignores a sequence of characters
+     * @param inhibs
+     *            are the ignored sub-blocks
+     * @return the index within the buffer of the first occurrence of the
+     *         specified substring, starting at the specified index. If it does
+     *         not occur as a substring, or pos < 0, or buffer.length() <= pos,
+     *         Int2(-1,-1) is returned. It returns 0 if (tag.length() == 0).
+     */
+    public Int2 indexOf(final String buffer, final String tag, int pos, String spec, Jump jump, String[][] inhibs) {
+        return indexIn(buffer, tag, pos, buffer.length(), spec, jump, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || posEnd >
+     * buffer.length()) => -1
+     */
+    public Int2 indexIn(final String buffer, final String tag, int posBegin, int posEnd) {
+        if (buffer == null || posBegin < 0 || posEnd <= 0 || posEnd <= posBegin || posEnd > buffer.length()) {
+            return Int2.NOT_FOUND;
+        }
+        if (tag == null || tag.length() == 0) {
+            return Int2.NOT_FOUND;
+        }
+        String substring = buffer.substring(posBegin, posEnd);
+        if (regex) {
+            Pattern pattern = compile(tag);
+            Matcher m = pattern.matcher(substring);
+            if (m.find()) {
+                return new Int2(posBegin + m.start(), posBegin + m.end());
+            } else {
+                return Int2.NOT_FOUND;
+            }
+        } else {
+            int i;
+            if (ignoreCase) {
+                i = substring.toLowerCase().indexOf(tag.toLowerCase());
+            } else {
+                i = substring.indexOf(tag);
+            }
+            if (i > -1) {
+                int b = posBegin + i;
+                return new Int2(b, b + tag.length());
+            } else {
+                return Int2.NOT_FOUND;
+            }
+        }
+    }
+
+    public Int2 indexIn(final String buffer, final String tag, int posBegin, int posEnd, String spec, String[][] inhibs) {
+        return indexIn(buffer, tag, posBegin, posEnd, spec, null, inhibs);
+    }
+
+    public Int2 indexIn(final String buffer, final String tag, int posBegin, int posEnd, String spec, Jump jump, String[][] inhibs) {
+        if (buffer == null || posBegin < 0 || posEnd <= 0 || posEnd <= posBegin || posEnd > buffer.length()) {
+            return Int2.NOT_FOUND;
+        }
+        if (spec == null && inhibs == null) {
+            return indexIn(buffer, tag, posBegin, posEnd);
+        }
+        if (tag == null) {
+            return Int2.NOT_FOUND;
+        }
+        int inhibs_size = 0;
+        if (inhibs != null) {
+            inhibs_size = inhibs.length;
+        }
+        Int2[] positions = new Int2[3 + inhibs_size];
+        for (int i = 0; i < positions.length; i++) {
+            positions[i] = new Int2(-2, -2);
+        }
+        while (posBegin > -1 && posBegin < posEnd) {
+            // Positions for tags and inhibs
+            if (positions[0].b() != -1 && spec != null && posBegin > positions[0].b()) {
+                positions[0] = indexIn(buffer, spec, posBegin, posEnd); // spec
+            }
+            if (positions[1].b() != -1 && posBegin > positions[1].b()) {
+                positions[1] = indexIn(buffer, tag, posBegin, posEnd); // tag
+            }
+            if (positions[2].b() != -1 && jump != null && posBegin > positions[2].b()) {
+                positions[2] = jump.begin(buffer, posBegin, posEnd); // jump
+            }
+            for (int i = 3; i < positions.length; i++) { // inhibsTag
+                if (positions[i].b() != -1 && posBegin > positions[i].b()) {
+                    positions[i] = indexIn(buffer, inhibs[i - 3][0], posBegin, posEnd);
+                }
+            }
+            // Get next position
+            int positionMin = posEnd;
+            int iPositionMin = -1;
+            for (int i = 0; i < positions.length; i++) {
+                if ((positions[i].b() > -1) && (positions[i].b() < positionMin)) {
+                    iPositionMin = i;
+                    positionMin = positions[i].b();
+                }
+            }
+            if (iPositionMin == -1 /* NOT FOUND */) {
+                return Int2.NOT_FOUND;
+            }
+            // Get the next element
+            if (iPositionMin == 0 /* spec */) {
+                posBegin = positions[iPositionMin].e();
+            } else if (iPositionMin == 1 /* tag */) {
+                return positions[iPositionMin];
+            } else if (iPositionMin == 2 /* jump */) {
+                posBegin = jump.end(buffer, positions[iPositionMin], posEnd, spec, inhibs);
+            } else if (iPositionMin >= 3 /* inhibsTag */) {
+                boolean forceNotRecursive;
+                if (inhibs[iPositionMin - 3].length >= 3 && inhibs[iPositionMin - 3][2] != null) {
+                    forceNotRecursive = inhibs[iPositionMin - 3][2].indexOf(TextSearch.FORCE_NOT_RECURSIVE) > -1;
+                } else {
+                    forceNotRecursive = false;
+                }
+                posBegin = blockIndexEndIn(buffer, inhibs[iPositionMin - 3][0], inhibs[iPositionMin - 3][1], positions[iPositionMin].b(), posEnd,
+                        (recursiveInhibs && !forceNotRecursive) ? true : false, spec, jump, (recursiveInhibs && !forceNotRecursive) ? inhibs : null).e();
+            }
+        };
+        return Int2.NOT_FOUND;
+    }
+
+    /*
+     * (endTag.length()==0) => buffer.length() (endTag not found || posBegin ne
+     * correspond pas a beginTag) => -1 (posBegin < 0 ||
+     * (buffer.length()-posBegin) <= 0) => -1
+     */
+    public Int2 blockIndexEndOf(final String buffer, String beginTag, String endTag, int posBegin, boolean recursive) {
+        return blockIndexEndOf(buffer, beginTag, endTag, posBegin, recursive, null, null);
+    }
+
+    public Int2 blockIndexEndOf(final String buffer, String beginTag, String endTag, int posBegin, boolean recursive, String spec, String[][] inhibs) {
+        return blockIndexEndOf(buffer, beginTag, endTag, posBegin, recursive, spec, null, inhibs);
+    }
+
+    public Int2 blockIndexEndOf(final String buffer, String beginTag, String endTag, int posBegin, boolean recursive, String spec, Jump jump, String[][] inhibs) {
+        return blockIndexEndIn(buffer, beginTag, endTag, posBegin, buffer.length(), recursive, spec, jump, inhibs);
+    }
+
+    /*
+     * (endTag.length()==0) => buffer.length() (endTag not found || posBegin ne
+     * correspond pas a beginTag) => -1 (posBegin < 0 || posEnd < 0 || posEnd <=
+     * posBegin || posEnd > buffer.length()) => -1
+     */
+    public Int2 blockIndexEndIn(final String buffer, String beginTag, String endTag, int posBegin, int posEnd, boolean recursive) {
+        return blockIndexEndIn(buffer, beginTag, endTag, posBegin, posEnd, recursive, null, null);
+    }
+
+    public Int2 blockIndexEndIn(final String buffer, String beginTag, String endTag, int posBegin, int posEnd, boolean recursive, String spec, String[][] inhibs) {
+        return blockIndexEndIn(buffer, beginTag, endTag, posBegin, posEnd, recursive, spec, null, inhibs);
+    }
+
+    public Int2 blockIndexEndIn(final String buffer, String beginTag, String endTag, int posBegin, int posEnd, boolean recursive, String spec, Jump jump, String[][] inhibs) {
+        if (buffer == null || posBegin < 0 || posEnd <= 0 || posEnd <= posBegin || posEnd > buffer.length()) {
+            return Int2.NOT_FOUND;
+        }
+        // Error cases
+        if (beginTag == null) {
+            return Int2.NOT_FOUND;
+        }
+        if (endTag == null) {
+            return Int2.NOT_FOUND;
+        }
+        Int2 posBeginInt2 = indexIn(buffer, beginTag, posBegin, posEnd);
+        if (beginTag.length() == 0) {
+            recursive = false;
+        } else if (posBeginInt2.b() != posBegin) {
+            return Int2.NOT_FOUND;
+        }
+        if (endTag.length() == 0) {
+            return new Int2(posEnd, posEnd);
+        }
+        // Block search
+        int nbBeginTagOuvert = 1;
+        int pos = posBeginInt2.e();
+        int inhibs_size = 0;
+        if (inhibs != null) {
+            inhibs_size = inhibs.length;
+        }
+        Int2[] positions = new Int2[4 + inhibs_size];
+        for (int i = 0; i < positions.length; i++) {
+            positions[i] = new Int2(-2, -2);
+        }
+        while (pos > -1 && pos < posEnd) {
+            // Positions for end, begin, and inhibs
+            if (positions[0].b() != -1 && spec != null && pos > positions[0].b()) {
+                positions[0] = indexIn(buffer, spec, pos, posEnd); // spec
+            }
+            if (positions[1].b() != -1 && pos > positions[1].b()) {
+                positions[1] = indexIn(buffer, endTag, pos, posEnd); // endTag
+            }
+            if (positions[2].b() != -1 && recursive && pos > positions[2].b()) {
+                positions[2] = indexIn(buffer, beginTag, pos, posEnd); // beginTag
+            }
+            if (positions[3].b() != -1 && jump != null && pos > positions[3].b()) {
+                positions[3] = jump.begin(buffer, pos, posEnd); // jump
+            }
+            for (int i = 4; i < positions.length; i++) { // inhibsTag
+                if (positions[i].b() != -1 && pos > positions[i].b()) {
+                    positions[i] = indexIn(buffer, inhibs[i - 4][0], pos, posEnd);
+                }
+            }
+            // Get next position
+            int positionMin = posEnd;
+            int iPositionMin = -1;
+            for (int i = 0; i < positions.length; i++) {
+                if ((positions[i].b() > -1) && (positions[i].b() < positionMin)) {
+                    iPositionMin = i;
+                    positionMin = positions[i].b();
+                }
+            }
+            if (iPositionMin == -1 /* NOT FOUND */) {
+                return Int2.NOT_FOUND;
+            }
+            // Get the next element
+            if (iPositionMin == 0 /* spec */) {
+                pos = positions[iPositionMin].e();
+            } else if (iPositionMin == 1 /* endTag */) {
+                nbBeginTagOuvert--;
+                pos = positions[iPositionMin].e();
+                if (!recursive) {
+                    return positions[iPositionMin];
+                }
+            } else if (iPositionMin == 2 /* beginTag */) {
+                nbBeginTagOuvert++;
+                pos = positions[iPositionMin].e();
+            } else if (iPositionMin == 3 /* jump */) {
+                pos = jump.end(buffer, positions[iPositionMin], posEnd, spec, inhibs);
+            } else if (iPositionMin >= 4 /* inhibsTag */) {
+                boolean forceNotRecursive;
+                if (inhibs[iPositionMin - 4].length >= 3 && inhibs[iPositionMin - 4][2] != null) {
+                    forceNotRecursive = inhibs[iPositionMin - 4][2].indexOf(TextSearch.FORCE_NOT_RECURSIVE) > -1;
+                } else {
+                    forceNotRecursive = false;
+                }
+                pos = blockIndexEndIn(buffer, inhibs[iPositionMin - 4][0], inhibs[iPositionMin - 4][1], positions[iPositionMin].b(), posEnd, (recursiveInhibs && !forceNotRecursive) ? true : false,
+                        spec, jump, (recursiveInhibs && !forceNotRecursive) ? inhibs : null).e();
+            }
+            if (nbBeginTagOuvert == 0) {
+                return positions[iPositionMin];
+            }
+        };
+        return Int2.NOT_FOUND;
+    }
+
+    /*
+     * (pos < 0 || (buffer.length()-pos) <= 0) => -1
+     */
+    public Int2 lastIndexOf(final String buffer, final String tag) {
+        return lastIndexOf(buffer, tag, 0);
+    }
+
+    public Int2 lastIndexOf(final String buffer, final String tag, int pos) {
+        return lastIndexOf(buffer, tag, pos, null, null);
+    }
+
+    public Int2 lastIndexOf(final String buffer, final String tag, String spec, String[][] inhibs) {
+        return lastIndexOf(buffer, tag, 0, spec, inhibs);
+    }
+
+    public Int2 lastIndexOf(final String buffer, final String tag, int pos, String spec, String[][] inhibs) {
+        return lastIndexIn(buffer, tag, pos, buffer.length(), spec, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || posEnd >
+     * buffer.length()) => -1
+     */
+    public Int2 lastIndexIn(final String buffer, final String tag, int posBegin, int posEnd) {
+        return lastIndexIn(buffer, tag, posBegin, posEnd, null, null);
+    }
+
+    public Int2 lastIndexIn(final String buffer, final String tag, int posBegin, int posEnd, String spec, String[][] inhibs) {
+        if (buffer == null || posBegin < 0 || posEnd <= 0 || posEnd <= posBegin || posEnd > buffer.length()) {
+            return Int2.NOT_FOUND;
+        }
+        Int2 i = indexIn(buffer, tag, posBegin, posEnd, spec, inhibs);
+        Int2 last_i = i;
+        while (i.b() > -1) {
+            i = indexIn(buffer, tag, i.e(), posEnd, spec, inhibs);
+            if (i.b() > -1) {
+                last_i = i;
+            }
+        }
+        return last_i;
+    }
+
+    /*
+     * (pos < 0) => {}
+     */
+    public Int2[] allIndexOf(final String buffer, final String tag) {
+        return allIndexOf(buffer, tag, 0);
+    }
+
+    public Int2[] allIndexOf(final String buffer, final String tag, int pos) {
+        return allIndexOf(buffer, tag, pos, null, null);
+    }
+
+    public Int2[] allIndexOf(final String buffer, final String tag, String spec, String[][] inhibs) {
+        return allIndexOf(buffer, tag, 0, spec, inhibs);
+    }
+
+    public Int2[] allIndexOf(final String buffer, final String tag, int pos, String spec, String[][] inhibs) {
+        return allIndexIn(buffer, tag, pos, buffer.length(), spec, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || (posEnd-posBegin) <=
+     * 0 || posEnd > buffer.length()) => {}
+     */
+    public Int2[] allIndexIn(final String buffer, final String tag, int posBegin, int posEnd) {
+        return allIndexIn(buffer, tag, posBegin, posEnd, null, null);
+    }
+
+    public Int2[] allIndexIn(final String buffer, final String tag, int posBegin, int posEnd, String spec, String[][] inhibs) {
+        if (buffer == null || posBegin < 0 || posEnd <= 0 || posEnd <= posBegin || posEnd > buffer.length()) {
+            return new Int2[] {};
+        }
+        List lst = new ArrayList();
+        Int2 i = indexIn(buffer, tag, posBegin, posEnd, spec, inhibs);
+        while (i.b() > -1) {
+            lst.add(i);
+            i = indexIn(buffer, tag, i.e(), posEnd, spec, inhibs);
+        }
+        return (Int2[]) lst.toArray(new Int2[lst.size()]);
+    }
+
+    public String[] splitOf(final String buffer, String[] separators, boolean keepSeparators) {
+        return splitOf(buffer, separators, keepSeparators, null, null);
+    }
+
+    public String[] splitOf(final String buffer, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        return splitOf(buffer, 0, separators, keepSeparators, spec, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || (buffer.length()-posBegin) <= 0) => {}
+     */
+    public String[] splitOf(final String buffer, int posBegin, String[] separators, boolean keepSeparators) {
+        return splitOf(buffer, posBegin, separators, keepSeparators, null, null);
+    }
+
+    public String[] splitOf(final String buffer, int posBegin, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        return splitIn(buffer, posBegin, buffer.length(), separators, keepSeparators, spec, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || posEnd >
+     * buffer.length()) => {}
+     */
+    public String[] splitIn(final String buffer, int posBegin, int posEnd, String[] separators, boolean keepSeparators) {
+        return splitIn(buffer, posBegin, posEnd, separators, keepSeparators, null, null);
+    }
+
+    public String[] splitIn(final String buffer, int posBegin, int posEnd, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        List list = split(buffer, posBegin, posEnd, separators, keepSeparators, spec, inhibs);
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+
+    private List split(final String buffer, int posBegin, int posEnd, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        List result = new LinkedList();
+        if (buffer == null || buffer.length() == 0 || posBegin < 0 || posEnd <= 0 || posEnd <= posBegin || posEnd > buffer.length()) {
+            return result;
+        }
+        if (separators == null) {
+            return result;
+        }
+        for (String separator : separators) {
+            if (separator != null && separator.length() > 0) {
+                Int2 index = indexIn(buffer, separator, posBegin, posEnd, spec, inhibs);
+                if (keepSeparators) {
+                    if (index.b() == posBegin) {
+                        return concat(buffer.substring(index.b(), index.e()), split(buffer, index.e(), posEnd, separators, keepSeparators, spec, inhibs));
+                    } else if (index.e() == buffer.length()) {
+                        return concat(split(buffer, posBegin, index.b(), separators, keepSeparators, spec, inhibs), buffer.substring(index.b(), index.e()));
+                    } else if (index.b() > -1) {
+                        return concat(split(buffer, posBegin, index.b(), separators, keepSeparators, spec, inhibs), buffer.substring(index.b(), index.e()),
+                                split(buffer, index.e(), posEnd, separators, keepSeparators, spec, inhibs));
+                    }
+                } else {
+                    if (index.b() == 0) {
+                        return split(buffer, index.e(), posEnd, separators, keepSeparators, spec, inhibs);
+                    } else if (index.e() == buffer.length()) {
+                        return split(buffer, posBegin, index.b(), separators, keepSeparators, spec, inhibs);
+                    } else if (index.b() > -1) {
+                        return concat(split(buffer, posBegin, index.b(), separators, keepSeparators, spec, inhibs), split(buffer, index.e(), posEnd, separators, keepSeparators, spec, inhibs));
+                    }
+                }
+            }
+        }
+        result.add(buffer.substring(posBegin, posEnd));
+        return result;
+    }
+
+    public Int2[] splitPositionsOf(final String buffer, String[] separators, boolean keepSeparators) {
+        return splitPositionsOf(buffer, separators, keepSeparators, null, null);
+    }
+
+    public Int2[] splitPositionsOf(final String buffer, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        return splitPositionsOf(buffer, 0, separators, keepSeparators, spec, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || (buffer.length()-posBegin) <= 0) => {}
+     */
+    public Int2[] splitPositionsOf(final String buffer, int posBegin, String[] separators, boolean keepSeparators) {
+        return splitPositionsOf(buffer, posBegin, separators, keepSeparators, null, null);
+    }
+
+    public Int2[] splitPositionsOf(final String buffer, int posBegin, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        return splitPositionsIn(buffer, posBegin, buffer.length(), separators, keepSeparators, spec, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || posEnd >
+     * buffer.length()) => {}
+     */
+    public Int2[] splitPositionsIn(final String buffer, int posBegin, int posEnd, String[] separators, boolean keepSeparators) {
+        return splitPositionsIn(buffer, posBegin, posEnd, separators, keepSeparators, null, null);
+    }
+
+    public Int2[] splitPositionsIn(final String buffer, int posBegin, int posEnd, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        List list = splitPositions(buffer, posBegin, posEnd, separators, keepSeparators, spec, inhibs);
+        return (Int2[]) list.toArray(new Int2[list.size()]);
+    }
+
+    private List splitPositions(final String buffer, int posBegin, int posEnd, String[] separators, boolean keepSeparators, String spec, String[][] inhibs) {
+        List result = new LinkedList();
+        if (buffer == null || buffer.length() == 0 || posBegin < 0 || posEnd <= 0 || posEnd <= posBegin || posEnd > buffer.length()) {
+            return result;
+        }
+        if (separators == null) {
+            return result;
+        }
+        Int2[] positions = new Int2[separators.length];
+        for (int i = 0; i < positions.length; i++) {
+            positions[i] = new Int2(-2, -2);
+        }
+        while (posBegin > -1 && posBegin < posEnd) {
+            for (int i = 0; i < positions.length; i++) {
+                if (positions[i].b() != -1 && posBegin > positions[i].b()) {
+                    if (separators[i] != null && separators[i].length() > 0) {
+                        positions[i] = indexIn(buffer, separators[i], posBegin, posEnd, spec, inhibs);
+                    } else {
+                        positions[i] = Int2.NOT_FOUND;
+                    }
+                }
+            }
+            // Get next position
+            int positionMin = posEnd;
+            int iPositionMin = -1;
+            for (int i = 0; i < positions.length; i++) {
+                if ((positions[i].b() > -1) && (positions[i].b() < positionMin)) {
+                    iPositionMin = i;
+                    positionMin = positions[i].b();
+                }
+            }
+            if (iPositionMin == -1 /* NOT FOUND */) {
+                if (posEnd > posBegin) {
+                    result.add(new Int2(posBegin, posEnd));
+                }
+                break;
+            } else {
+                if (positions[iPositionMin].b() > posBegin) {
+                    result.add(new Int2(posBegin, positions[iPositionMin].b()));
+                }
+                if (keepSeparators) {
+                    result.add(positions[iPositionMin]);
+                }
+                posBegin = positions[iPositionMin].e();
+            }
+        }
+        return result;
+    }
+
+    private List concat(List t1, Object o, List t2) {
+        t1.add(o);
+        t1.addAll(t2);
+        return t1;
+    }
+
+    private List concat(List t1, List t2) {
+        t1.addAll(t2);
+        return t1;
+    }
+
+    private List concat(List t1, Object o) {
+        t1.add(o);
+        return t1;
+    }
+
+    private List concat(Object o, List t2) {
+        t2.add(0, o);
+        return t2;
+    }
+
+    /*
+     * Sample : <li> buffer =1:aaa.bbb </li> <li> sRegex = \[0-9]:ID.ID </li>
+     * <li> arg = ID </li> <li> argRegex = [a-zA-Z]+ </li> <p> => {aaa,bbb}
+     */
+    public String[] extractValues(final String buffer, String sRegex, String arg, String argRegex) {
+        if (buffer == null || sRegex == null || arg == null || argRegex == null) {
+            return new String[] {};
+        }
+        List res = new ArrayList();
+        String[] regex = splitOf(sRegex, new String[] { arg }, true/* keepSeparators */, null, null);
+        boolean posOK = true;
+        int iPosOK = 0;
+        for (int i = 0; posOK && i < regex.length; i++) {
+            String ex = regex[i];
+            boolean isArg = ex.equals(arg);
+            if (isArg) {
+                ex = argRegex;
+            }
+            Int2 pos = indexOf(buffer, ex, iPosOK);
+            if (isArg) {
+                res.add(buffer.substring(pos.b(), pos.e()));
+            }
+            posOK = (pos.b() == iPosOK);
+            iPosOK = pos.e();
+        }
+        posOK = (iPosOK == buffer.length());
+        if (posOK) {
+            return (String[]) res.toArray(new String[res.size()]);
+        } else {
+            return new String[] {};
+        }
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || posEnd >
+     * buffer.length()) => -1
+     */
+    public Int2 trim(final String buffer, int posBegin, int posEnd) {
+        if (buffer == null) {
+            return Int2.NOT_FOUND;
+        }
+        if (posBegin < 0 || posBegin >= buffer.length()) {
+            return Int2.NOT_FOUND;
+        }
+        if (posEnd < 0 || posEnd > buffer.length()) {
+            return Int2.NOT_FOUND;
+        }
+        if (posBegin > posEnd) {
+            return Int2.NOT_FOUND;
+        }
+        while (posBegin < posEnd) {
+            char c = buffer.charAt(posBegin);
+            if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+                posBegin++;
+            } else {
+                break;
+            }
+        }
+        while (posEnd > posBegin) {
+            char c = buffer.charAt(posEnd - 1);
+            if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+                posEnd--;
+            } else {
+                break;
+            }
+        }
+        if (posBegin < posEnd) {
+            return new Int2(posBegin, posEnd);
+        } else {
+            return Int2.NOT_FOUND;
+        }
+    }
+
+    /*
+     * (pos < 0) => 0
+     */
+    public int countOf(final String buffer, final String tag) {
+        return countOf(buffer, tag, 0);
+    }
+
+    public int countOf(final String buffer, final String tag, int pos) {
+        return countOf(buffer, tag, pos, null, null);
+    }
+
+    public int countOf(final String buffer, final String tag, String spec, String[][] inhibs) {
+        return countOf(buffer, tag, 0, spec, inhibs);
+    }
+
+    public int countOf(final String buffer, final String tag, int pos, String spec, String[][] inhibs) {
+        return countIn(buffer, tag, pos, buffer.length(), spec, inhibs);
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || (posEnd-posBegin) <=
+     * 0 || posEnd > buffer.length()) => 0
+     */
+    public int countIn(final String buffer, final String tag, int posBegin, int posEnd) {
+        return countIn(buffer, tag, posBegin, posEnd, null, null);
+    }
+
+    public int countIn(final String buffer, final String tag, int posBegin, int posEnd, String spec, String[][] inhibs) {
+        return allIndexIn(buffer, tag, posBegin, posEnd, spec, inhibs).length;
+    }
+
+    /*
+     * (buffer == null || index < 0 || index > buffer.length()) => 0
+     */
+    public int lineNumber(File file, int index) {
+        Object[] object = (Object[]) lineNumberFileContentMap.get(file);
+        if (object == null) {
+            object = new Object[2];
+            object[0] = new HashMap();
+            ((Map) object[0]).put(new Integer(0), new Integer(1));
+            String buffer = Resources.getFileContent(file).toString();
+            object[1] = buffer;
+            Int2[] endLines = allIndexOf(buffer, "\n"); //$NON-NLS-1$
+            for (int i = 0; i < endLines.length; i++) {
+                ((Map) object[0]).put(new Integer(endLines[i].e()), new Integer(i + 2));
+            }
+            lineNumberFileContentMap.put(file, object);
+        }
+        Map firstCharToLine = (Map) object[0];
+        String buffer = (String) object[1];
+        int firstChar = index;
+        while (firstChar > 0 && buffer.charAt(firstChar - 1) != '\n') {
+            firstChar--;
+        }
+        Integer lineNumber = (Integer) firstCharToLine.get(new Integer(firstChar));
+        if (lineNumber != null) {
+            return lineNumber.intValue();
+        } else {
+            AcceleoToolsPlugin.getDefault().log(AcceleoToolsMessages.getString("TextSearch.CharacterLineNotFound", new Object[] { Integer.toString(index), file.getAbsolutePath(), }), true); //$NON-NLS-1$
+            return 0;
+        }
+    }
+
+    private FileContentMap lineNumberFileContentMap = new FileContentMap(5, true);
+
+    /*
+     * (buffer == null || index < 0 || index > buffer.length()) => 0
+     */
+    public int lineNumber(final String buffer, int index) {
+        if (buffer != null && index >= 0 && index < buffer.length()) {
+            if (refBuffer.equals(buffer) && index >= refIndex) {
+                for (int i = refIndex; i < index; i++) {
+                    if (buffer.charAt(i) == '\n') {
+                        refLineNumber++;
+                    }
+                }
+            } else {
+                refLineNumber = 1;
+                for (int i = 0; i < index; i++) {
+                    if (buffer.charAt(i) == '\n') {
+                        refLineNumber++;
+                    }
+                }
+            }
+            refBuffer = buffer;
+            refIndex = index;
+            return refLineNumber;
+        } else {
+            return 0;
+        }
+    }
+
+    private String refBuffer = ""; //$NON-NLS-1$
+
+    private int refIndex = 0;
+
+    private int refLineNumber = 1;
+
+    /*
+     * (buffer == null || index <= 0 || index > buffer.length()) => 0
+     */
+    public int columnNumber(final String buffer, int index) {
+        if (buffer != null && index > 0 && index < buffer.length()) {
+            int column = 0;
+            for (int i = index - 1; i >= 0; i--) {
+                if (buffer.charAt(i) != '\n') {
+                    column++;
+                } else {
+                    break;
+                }
+            }
+            return column;
+        } else {
+            return 0;
+        }
+    }
+
+    /*
+     * (posBegin < 0 || posEnd < 0 || posEnd <= posBegin || posEnd >
+     * buffer.length()) => buffer
+     */
+    public String replaceAllIn(final String buffer, String string, String replacementString, int posBegin, int posEnd, String[][] inhibs) {
+        if (buffer == null) {
+            return null;
+        }
+        StringBuffer result = new StringBuffer(buffer);
+        Int2[] positions = allIndexIn(buffer, string, posBegin, posEnd, null, inhibs);
+        if (positions.length > 0) {
+            for (int i = positions.length - 1; i >= 0; i--) {
+                Int2 pos = positions[i];
+                result.replace(pos.b(), pos.e(), replacementString);
+            }
+        }
+        return result.toString();
+    }
+
+}
diff --git a/update/category.xml b/update/category.xml
new file mode 100644
index 0000000..275a115
--- /dev/null
+++ b/update/category.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<site>
+  <feature id="org.eclipse.sirius.query.legacy.feature" version="2.10.0.qualifier">
+    <category name="org.eclipse.sirius.legacy"/>
+  </feature>
+  <feature id="org.eclipse.sirius.query.legacy.feature.source" version="2.10.0.qualifier">
+    <category name="org.eclipse.sirius.legacy"/>
+  </feature>
+  <category-def name="org.eclipse.sirius.legacy" label="Sirius Support for Legacy Features">
+  </category-def>
+</site>