blob: 71678ce9c27093fe648ecbdadb60ae14e255e1eb [file] [log] [blame]
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.1.2, mkdocs-material-7.1.5">
<title>Code Generation (EGL) - Epsilon</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.bde7dde4.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.ef6f36e2.min.css">
<meta name="theme-color" content="#000000">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
<style>:root{--md-text-font-family:"Roboto";--md-code-font-family:"Roboto Mono"}</style>
<link rel="stylesheet" href="../../assets/stylesheets/mermaid.css">
<link rel="stylesheet" href="../../assets/javascript/google-code-prettify/prettify.css">
<link rel="stylesheet" href="https://unpkg.com/mermaid@8.5.1/dist/mermaid.css">
<link rel="stylesheet" href="../../assets/stylesheets/slick.css">
<link rel="stylesheet" href="../../assets/stylesheets/slick-theme.css">
<link rel="stylesheet" href="../../assets/stylesheets/extra.css">
<script>
window.ga = window.ga || function() {
(ga.q = ga.q || []).push(arguments)
}
ga.l = +new Date
/* Setup integration and send page view */
ga("create", "UA-184785655-1", "auto")
ga("set", "anonymizeIp", true)
ga("send", "pageview")
/* Register handler to log search on blur */
document.addEventListener("DOMContentLoaded", () => {
if (document.forms.search) {
var query = document.forms.search.query
query.addEventListener("blur", function() {
if (this.value) {
var path = document.location.pathname;
ga("send", "pageview", path + "?q=" + this.value)
}
})
}
})
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
</head>
<body dir="ltr" data-md-color-scheme="" data-md-color-primary="black" data-md-color-accent="orange">
<script>function __prefix(e){return new URL("../..",location).pathname+"."+e}function __get(e,t=localStorage){return JSON.parse(t.getItem(__prefix(e)))}</script>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#the-epsilon-generation-language-egl" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="Epsilon" class="md-header__button md-logo" aria-label="Epsilon" data-md-component="logo">
<img src="../../assets/images/epsilon-white-background.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Epsilon
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Code Generation (EGL)
</span>
</div>
</div>
</div>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" data-md-state="active" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
</label>
<button type="reset" class="md-search__icon md-icon" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://git.eclipse.org/c/epsilon/org.eclipse.epsilon.git/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
Git repository @ Eclipse
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="Epsilon" class="md-nav__button md-logo" aria-label="Epsilon" data-md-component="logo">
<img src="../../assets/images/epsilon-white-background.png" alt="logo">
</a>
Epsilon
</label>
<div class="md-nav__source">
<a href="https://git.eclipse.org/c/epsilon/org.eclipse.epsilon.git/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
Git repository @ Eclipse
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../.." class="md-nav__link">
Home
</a>
</li>
<li class="md-nav__item">
<a href="../../download/" class="md-nav__link">
Download
</a>
</li>
<li class="md-nav__item">
<a href="../../getting-started/" class="md-nav__link">
Getting Started
</a>
</li>
<li class="md-nav__item">
<a href="../../live" class="md-nav__link">
Playground
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5" type="checkbox" id="__nav_5" checked>
<label class="md-nav__link" for="__nav_5">
Documentation
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Documentation" data-md-level="1">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Documentation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../" class="md-nav__link">
Overview
</a>
</li>
<li class="md-nav__item">
<a href="../emc/" class="md-nav__link">
Model Connectivity
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_3" type="checkbox" id="__nav_5_3" checked>
<label class="md-nav__link" for="__nav_5_3">
Languages
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Languages" data-md-level="2">
<label class="md-nav__title" for="__nav_5_3">
<span class="md-nav__icon md-icon"></span>
Languages
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../eol/" class="md-nav__link">
Object Language (EOL)
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Code Generation (EGL)
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
Code Generation (EGL)
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#abstract-syntax" class="md-nav__link">
Abstract Syntax
</a>
</li>
<li class="md-nav__item">
<a href="#concrete-syntax" class="md-nav__link">
Concrete Syntax
</a>
<nav class="md-nav" aria-label="Concrete Syntax">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#comments-and-markers" class="md-nav__link">
Comments and Markers
</a>
</li>
<li class="md-nav__item">
<a href="#user-defined-operations" class="md-nav__link">
User-Defined Operations
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#the-outputbuffer" class="md-nav__link">
The OutputBuffer
</a>
</li>
<li class="md-nav__item">
<a href="#co-ordination" class="md-nav__link">
Co-ordination
</a>
<nav class="md-nav" aria-label="Co-ordination">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#the-template-type" class="md-nav__link">
The Template type
</a>
</li>
<li class="md-nav__item">
<a href="#the-templatefactory-object" class="md-nav__link">
The TemplateFactory object
</a>
</li>
<li class="md-nav__item">
<a href="#an-example-of-co-ordination-with-egl" class="md-nav__link">
An Example of Co-ordination with EGL
</a>
</li>
<li class="md-nav__item">
<a href="#customising-the-co-ordination-engine" class="md-nav__link">
Customising the Co-ordination Engine
</a>
<nav class="md-nav" aria-label="Customising the Co-ordination Engine">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#implementing-a-custom-templatefactory" class="md-nav__link">
Implementing a custom TemplateFactory
</a>
</li>
<li class="md-nav__item">
<a href="#using-a-custom-templatefactory" class="md-nav__link">
Using a custom TemplateFactory
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
Summary
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#merge-engine" class="md-nav__link">
Merge Engine
</a>
</li>
<li class="md-nav__item">
<a href="#formatters" class="md-nav__link">
Formatters
</a>
<nav class="md-nav" aria-label="Formatters">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#using-a-formatter" class="md-nav__link">
Using a Formatter
</a>
</li>
<li class="md-nav__item">
<a href="#implementing-a-custom-formatter" class="md-nav__link">
Implementing a Custom Formatter
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#traceability" class="md-nav__link">
Traceability
</a>
</li>
<li class="md-nav__item">
<a href="#additional-resources" class="md-nav__link">
Additional Resources
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../evl/" class="md-nav__link">
Model Validation (EVL)
</a>
</li>
<li class="md-nav__item">
<a href="../etl/" class="md-nav__link">
Model Transformation (ETL)
</a>
</li>
<li class="md-nav__item">
<a href="../ecl/" class="md-nav__link">
Model Comparison (ECL)
</a>
</li>
<li class="md-nav__item">
<a href="../eml/" class="md-nav__link">
Model Merging (EML)
</a>
</li>
<li class="md-nav__item">
<a href="../epl/" class="md-nav__link">
Pattern Matching (EPL)
</a>
</li>
<li class="md-nav__item">
<a href="../flock/" class="md-nav__link">
Model Migration (Flock)
</a>
</li>
<li class="md-nav__item">
<a href="../emg/" class="md-nav__link">
Model Generation (EMG)
</a>
</li>
<li class="md-nav__item">
<a href="../eunit/" class="md-nav__link">
Unit Testing (EUnit)
</a>
</li>
<li class="md-nav__item">
<a href="../pinset/" class="md-nav__link">
Dataset Extraction (Pinset)
</a>
</li>
<li class="md-nav__item">
<a href="../ewl/" class="md-nav__link">
Wizard Language (EWL)
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_4" type="checkbox" id="__nav_5_4" >
<label class="md-nav__link" for="__nav_5_4">
Tools
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Tools" data-md-level="2">
<label class="md-nav__title" for="__nav_5_4">
<span class="md-nav__icon md-icon"></span>
Tools
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../picto/" class="md-nav__link">
Picto
</a>
</li>
<li class="md-nav__item">
<a href="../flexmi/" class="md-nav__link">
Flexmi
</a>
</li>
<li class="md-nav__item">
<a href="../eugenia/" class="md-nav__link">
Eugenia
</a>
</li>
<li class="md-nav__item">
<a href="../exeed/" class="md-nav__link">
Exeed
</a>
</li>
<li class="md-nav__item">
<a href="../modelink/" class="md-nav__link">
Modelink
</a>
</li>
<li class="md-nav__item">
<a href="../hutn/" class="md-nav__link">
HUTN
</a>
</li>
<li class="md-nav__item">
<a href="../workflow/" class="md-nav__link">
Workflow (Ant tasks)
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../articles/" class="md-nav__link">
Articles
</a>
</li>
<li class="md-nav__item">
<a href="../../examples/" class="md-nav__link">
Examples
</a>
</li>
<li class="md-nav__item">
<a href="https://www.youtube.com/epsilondevs" class="md-nav__link">
Screencasts
</a>
</li>
<li class="md-nav__item">
<a href="https://www.youtube.com/playlist?list=PLRwHao6Ue0YUecg7vEUQTrtySIWwrd_mI" class="md-nav__link">
Lectures
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5_9" type="checkbox" id="__nav_5_9" >
<label class="md-nav__link" for="__nav_5_9">
Javadoc
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Javadoc" data-md-level="2">
<label class="md-nav__title" for="__nav_5_9">
<span class="md-nav__icon md-icon"></span>
Javadoc
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://download.eclipse.org/epsilon/stable-javadoc/" class="md-nav__link">
Stable
</a>
</li>
<li class="md-nav__item">
<a href="https://download.eclipse.org/epsilon/interim-javadoc/" class="md-nav__link">
Interim
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_6" type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6">
Issues
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Issues" data-md-level="1">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Issues
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://bugs.eclipse.org/bugs/enter_bug.cgi?product=epsilon" class="md-nav__link">
Report a new issue
</a>
</li>
<li class="md-nav__item">
<a href="https://bugs.eclipse.org/bugs/buglist.cgi?product=epsilon&cmdtype=doit&order=Reuse+same+sort+as+last+time&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=blocker&bug_severity=critical&bug_severity=major&bug_severity=normal&bug_severity=minor&bug_severity=trivial" class="md-nav__link">
View open bugs
</a>
</li>
<li class="md-nav__item">
<a href="https://bugs.eclipse.org/bugs/buglist.cgi?product=epsilon&cmdtype=doit&order=Reuse+same+sort+as+last+time&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=enhancement" class="md-nav__link">
View enhancement requests
</a>
</li>
<li class="md-nav__item">
<a href="https://bugs.eclipse.org/bugs/buglist.cgi?bug_status=RESOLVED&list_id=17694438&product=epsilon&query_format=advanced" class="md-nav__link">
View issues resolved since the last stable release
</a>
</li>
<li class="md-nav__item">
<a href="https://bugs.eclipse.org/bugs/buglist.cgi?product=epsilon&cmdtype=doit&order=Reuse+same+sort+as+last+time" class="md-nav__link">
View all issues
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7" type="checkbox" id="__nav_7" >
<label class="md-nav__link" for="__nav_7">
Community
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Community" data-md-level="1">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Community
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7_1" type="checkbox" id="__nav_7_1" >
<label class="md-nav__link" for="__nav_7_1">
Who is using Epsilon?
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Who is using Epsilon?" data-md-level="2">
<label class="md-nav__title" for="__nav_7_1">
<span class="md-nav__icon md-icon"></span>
Who is using Epsilon?
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../users/" class="md-nav__link">
Industry
</a>
</li>
<li class="md-nav__item">
<a href="../../users/education/" class="md-nav__link">
Education
</a>
</li>
<li class="md-nav__item">
<a href="../../users/open-source/" class="md-nav__link">
Open-source Projects
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="https://projects.eclipse.org/projects/modeling.epsilon/who" class="md-nav__link">
Who is developing Epsilon?
</a>
</li>
<li class="md-nav__item">
<a href="https://www.eclipse.org/forums/index.php/f/22/" class="md-nav__link">
Forum
</a>
</li>
<li class="md-nav__item">
<a href="../../professional-services" class="md-nav__link">
Professional Services
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7_5" type="checkbox" id="__nav_7_5" >
<label class="md-nav__link" for="__nav_7_5">
Social Media
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" aria-label="Social Media" data-md-level="2">
<label class="md-nav__title" for="__nav_7_5">
<span class="md-nav__icon md-icon"></span>
Social Media
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://twitter.com/eclipseepsilon" class="md-nav__link">
Twitter
</a>
</li>
<li class="md-nav__item">
<a href="https://youtube.com/epsilondevs" class="md-nav__link">
YouTube
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../labs/" class="md-nav__link">
Epsilon Labs
</a>
</li>
<li class="md-nav__item">
<a href="../../faq/" class="md-nav__link">
Frequently Asked Questions
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../branding/" class="md-nav__link">
Branding
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#abstract-syntax" class="md-nav__link">
Abstract Syntax
</a>
</li>
<li class="md-nav__item">
<a href="#concrete-syntax" class="md-nav__link">
Concrete Syntax
</a>
<nav class="md-nav" aria-label="Concrete Syntax">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#comments-and-markers" class="md-nav__link">
Comments and Markers
</a>
</li>
<li class="md-nav__item">
<a href="#user-defined-operations" class="md-nav__link">
User-Defined Operations
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#the-outputbuffer" class="md-nav__link">
The OutputBuffer
</a>
</li>
<li class="md-nav__item">
<a href="#co-ordination" class="md-nav__link">
Co-ordination
</a>
<nav class="md-nav" aria-label="Co-ordination">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#the-template-type" class="md-nav__link">
The Template type
</a>
</li>
<li class="md-nav__item">
<a href="#the-templatefactory-object" class="md-nav__link">
The TemplateFactory object
</a>
</li>
<li class="md-nav__item">
<a href="#an-example-of-co-ordination-with-egl" class="md-nav__link">
An Example of Co-ordination with EGL
</a>
</li>
<li class="md-nav__item">
<a href="#customising-the-co-ordination-engine" class="md-nav__link">
Customising the Co-ordination Engine
</a>
<nav class="md-nav" aria-label="Customising the Co-ordination Engine">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#implementing-a-custom-templatefactory" class="md-nav__link">
Implementing a custom TemplateFactory
</a>
</li>
<li class="md-nav__item">
<a href="#using-a-custom-templatefactory" class="md-nav__link">
Using a custom TemplateFactory
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
Summary
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#merge-engine" class="md-nav__link">
Merge Engine
</a>
</li>
<li class="md-nav__item">
<a href="#formatters" class="md-nav__link">
Formatters
</a>
<nav class="md-nav" aria-label="Formatters">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#using-a-formatter" class="md-nav__link">
Using a Formatter
</a>
</li>
<li class="md-nav__item">
<a href="#implementing-a-custom-formatter" class="md-nav__link">
Implementing a Custom Formatter
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#traceability" class="md-nav__link">
Traceability
</a>
</li>
<li class="md-nav__item">
<a href="#additional-resources" class="md-nav__link">
Additional Resources
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="the-epsilon-generation-language-egl">The Epsilon Generation Language (EGL)<a class="headerlink" href="#the-epsilon-generation-language-egl" title="Permanent link">&para;</a></h1>
<p>EGL is a model-to-text transformation (M2T) language that can be used to transform models into various types of textual artefact, including code (e.g. Java), reports (e.g. in HTML/LaTeX), images (e.g. using <a href="https://graphviz.org">Graphviz</a>), formal specifications, or even entire applications comprising code in multiple languages (e.g. HTML, Javascript and CSS).</p>
<p>EGL is a <em>template-based</em> language (i.e. EGL programs resemble the text that they generate), and provides several features that simplify and support the generation of text from models, including: </p>
<ul>
<li>a sophisticated and language-independent merging engine (for preserving hand-written sections of generated text), </li>
<li>an extensible template system (for generating text to a variety of sources, such as a file on disk, a database server, or even as a response issued by a web server), </li>
<li>formatting algorithms (for producing generated text that is well-formatted and hence readable), and traceability mechanisms (for linking generated text with source models).</li>
</ul>
<div class="admonition tip">
<p class="admonition-title">Try EGL online</p>
<p>You can run and fiddle with an EGL template that generates an ASCII-based Gantt chart from a project scheduling model in the <a href="../../live/?egl">online Epsilon Playground</a>.</p>
</div>
<h2 id="abstract-syntax">Abstract Syntax<a class="headerlink" href="#abstract-syntax" title="Permanent link">&para;</a></h2>
<p>The figure below shows the abstract syntax of EGL's core functionality.</p>
<div class="admonition info">
<p class="admonition-title">Info</p>
<p>As with most languages in Epsilon, EGL uses <a href="../eol">EOL</a> as its expression language. This page only documents the additional syntax and semantics that EGL provides on top of EOL.</p>
</div>
<div class="mermaid mermaid-100">classDiagram
class EglSection {
+getChildren(): List
+getText(): String
}
class EglDynamicSection {
+getText(): String
}
class EglStaticSection {
+getText(): String
}
class EglShortcutSection {
+getText(): String
}
EglSection &lt;|-- EglDynamicSection
EglSection &lt;|-- EglStaticSection
EglSection &lt;|-- EglShortcutSection</div>
<p>Conceptually, an EGL program comprises one or more <em>sections</em>. The contents of static sections are emitted verbatim and appear directly in the generated text. The contents of dynamic sections are executed and are used to control the text that is generated.</p>
<p>In its dynamic sections, EGL re-uses EOL's syntax for structuring program control flow, performing model inspection and navigation, and defining custom operations. In addition, EGL provides an EOL object, <code>out</code>, which is used in dynamic sections to perform operations on the generated text, such as appending and removing strings; and specifying the type of text to be generated.</p>
<p>EGL also provides syntax for defining <em>dynamic output</em> sections, which provide a convenient shorthand for outputting text from within dynamic sections. Similar syntax is often provided by template-based code generators.</p>
<h2 id="concrete-syntax">Concrete Syntax<a class="headerlink" href="#concrete-syntax" title="Permanent link">&para;</a></h2>
<p>The concrete syntax of EGL closely resembles the style of other template-based code generation languages, such as PHP. The tag pair <em>[% %]</em> is used to delimit a dynamic section. Any text not enclosed in such a tag pair is contained in a static section. The listing below illustrates the use of dynamic and static sections to form a basic EGL template.</p>
<pre class="prettyprint lang-egl"><code>[% for (i in Sequence{1..5}) { %]
i is [%=i%]
[% } %]</code></pre>
<p>Executing the EGL template above would produce the generated text below. The <em>[%=expr%]</em> construct (line 2) is shorthand for <em>[% out.print(expr); %]</em>, which appends <em>expr</em> to the output generated by the transformation.</p>
<div class="highlight"><pre><span></span><code>i is 1
i is 2
i is 3
i is 4
i is 5
</code></pre></div>
<p>Any EOL statement can be contained in the dynamic sections of an EGL template. For example, the EGL template shown below generates text from a model that conforms to a metamodel that describes an object-oriented system.</p>
<pre class="prettyprint lang-egl"><code>[% for (c in Class.all) { %]
[%=c.name%]
[% } %]</code></pre>
<h3 id="comments-and-markers">Comments and Markers<a class="headerlink" href="#comments-and-markers" title="Permanent link">&para;</a></h3>
<p>Inside an EGL dynamic section, EOL's comment syntax can be used. Additionally, EGL adds syntax for comment blocks <code>[* this is a comment *]</code> and marker blocks <code>[*- this is a marker *]</code>. Marker blocks are highlighted by the EGL editor and EGL outline view in Eclipse.</p>
<h3 id="user-defined-operations">User-Defined Operations<a class="headerlink" href="#user-defined-operations" title="Permanent link">&para;</a></h3>
<p>Like EOL, EGL permits users to define re-usable units of code via
operations.</p>
<pre class="prettyprint lang-egl"><code>[% c.declaration(); %]
[% operation Class declaration() { %]
[%=self.visibility%] class [%=self.name%] {}
[% } %]</code></pre>
<p>In EGL, user-defined operations are defined in dynamic sections, but may mix static and dynamic sections in their bodies. Consider, for example, the EGL code in the listing above, which emits a declaration for a Java class (e.g. <code>public class Foo {}</code>). Lines 2-4 declare the operation. Note that the start and the end of the operation's declaration (on lines 2 and 4, respectively) are contained in dynamic sections. The body of the operation (line 3), however, mixes static and dynamic output sections. Finally, note that the operation is invoked from a dynamic section (line 1). It is worth noting that any loose (i.e. not contained in other operations) dynamic or static sections below the first operation of a template will be ignored at runtime.</p>
<p>When a user-defined operation is invoked, any static or dynamic sections contained in the body of the operation are immediately appended to the generated text. Sometimes, however, it is desirable to manipulate the text produced by an operation before it is appended to the generated text. To this end, EGL defines the <code>@template</code> annotation which can applied to operations to indicate that any text generated by the operation must be returned from the operation and not appended to the generated text. For example, the EGL program in the listing above could be rewritten using a <code>@template</code> annotation, as demonstrated below.</p>
<pre class="prettyprint lang-egl"><code>[%=c.declaration()%]
[% @template
operation Class declaration() { %]
[%=self.visibility%] class [%=self.name%] {}
[% } %]</code></pre>
<p>There is a subtle difference between the way in which standard (i.e. unannotated) operations and <code>@template</code> operations are invoked. Compare the first line of the two listings above. The former uses a dynamic section, because invoking the operation causes the evaluation of its body to be appended to the text generated by this program. By contrast, the latter uses a dynamic output section to append the result returned by the <code>@template</code> operation to the text generated by this program.</p>
<p>In general, <code>@template</code> operations afford more flexibility than standard operations. For example, line 1 of the listing above could perform some manipulation of the text returned by the <code>declaration()</code> operation before the text is outputted. Therefore, <code>@template</code> operations provide a mechanism for re-using common pieces of a code generator, without sacrificing the flexibility to slightly alter text before it is emitted. Standard (unannotated) operations also permit re-use, but in a less flexible manner.</p>
<p>Finally, it is worth noting that user-defined operations in EGL do not have to generate text. For example, the following listing illustrates two operations defined in an EGL program that do not generate any text. The former is a query that returns a Boolean value, while the latter alters the model, and does not return a value.</p>
<pre class="prettyprint lang-egl"><code>[%
operation Class isAnonymous() : Boolean {
return self.name.isUndefined();
}
operation removeOneClass() {
delete Class.all.random();
}
%]</code></pre>
<h2 id="the-outputbuffer">The OutputBuffer<a class="headerlink" href="#the-outputbuffer" title="Permanent link">&para;</a></h2>
<p>As an EGL program is executed, text is appended to a data structure termed the <em>OutputBuffer</em>. In every EGL program, the <em>OutputBuffer</em> is accessible via the <code>out</code> built-in variable. The <em>OutputBuffer</em> provides operations for appending to and removing from the buffer, and for merging generated text with existing text.</p>
<p>For many EGL programs, interacting directly with the <em>OutputBuffer</em> is unnecessary. The contents of static and dynamic output sections are sent directly to the <em>OutputBuffer</em>, and no operation of the <em>OutputBuffer</em> need be invoked directly. However, in cases when generated text must be sent to the <em>OutputBuffer</em> from dynamic sections, or when generated text must be merged with existing text, the operations of <em>OutputBuffer</em> are provided in the table below. The [merge engine section]](#merge-engine) discusses merging generated and existing text, and presents several examples of invoking the operations of <em>OutputBuffer</em>.</p>
<table>
<thead>
<tr>
<th>Signature</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>chop(numberOfChars : Integer)</td>
<td>Removes the specified number of characters from the end of the buffer</td>
</tr>
<tr>
<td>print(object : Any)</td>
<td>Appends a string representation of the specified object to the buffer</td>
</tr>
<tr>
<td>println(object : Any)</td>
<td>Appends a string representation of the specified object and a new line to the buffer</td>
</tr>
<tr>
<td>println()</td>
<td>Appends a new line to the buffer</td>
</tr>
<tr>
<td>setContentType(contentType : String)</td>
<td>Updates the content type of this template. Subsequent calls to <code>preserve</code> or <code>startPreserve</code> that do not specify a style of comment will use the style of comment defined by the specified content type.</td>
</tr>
<tr>
<td>preserve(id : String, enabled : Boolean, contents : String)</td>
<td>Appends a protected region to the buffer with the given identifier, enabled state and contents. Uses the current content type to determine how to format the start and end markers.</td>
</tr>
<tr>
<td>preserve(startComment : String, endComment : String, id : String, enabled : Boolean, contents : String)</td>
<td>Appends a protected region to the buffer with the given identifier, enabled state and contents. Uses the first two parameters as start and end markers.</td>
</tr>
<tr>
<td>startPreserve(id : String, enabled : Boolean)</td>
<td>Begins a protected region by appending the start marker for a protected region to the buffer with the given identifier and enabled state. Uses the current content type to determine how to format the start and end markers</td>
</tr>
<tr>
<td>startPreserve(startComment : String, endComment : String, id : String, enabled : Boolean)</td>
<td>Begins a protected region by appending the start marker to the buffer with the given identifier and enabled state. Uses the first two parameters as start and end markers.</td>
</tr>
<tr>
<td>stopPreserve()</td>
<td>Ends the current protected region by appending the end marker to the buffer. This operation should be invoked only if there a protected region is currently open (i.e. has been started by invoking <code>startPreserve</code> but not yet stopped by invoking <code>stopPreserve</code>).</td>
</tr>
</tbody>
</table>
<h2 id="co-ordination">Co-ordination<a class="headerlink" href="#co-ordination" title="Permanent link">&para;</a></h2>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The recommended way to coordinate the execution of EGL templates is using the <a href="../egx/">EGX rule-based language</a>. This section describes an imperative way to invoke EGL templates which pre-dates EGX and should only be used as a fall-back in case the semantics of EGX are not sufficient for the task at hand.</p>
</div>
<p>In the large, M2T transformations are used to generate text to various destinations. For example, code generators often produce files on disk, and web applications often generate text as part of the response for a resource on the web server. Text might be generated to a network socket during interprocess communication, or as a query that runs on a database. Furthermore, (parts of) a single M2T transformation might be re-used in different contexts. A M2T transformation that generates files on disk today might be re-purposed to generate the response from a web server tomorrow.</p>
<p>Given these concerns, EGL provides a co-ordination engine that provides mechanisms for modularising M2T transformations, and for controlling the destinations to which text is generated. The EGL co-ordination engine fulfils three requirements:</p>
<ol>
<li>
<p><strong>Reusability</strong>: the co-ordination engine allows EGL programs to be decomposed into one or more templates, which can be shared between EGL programs.</p>
</li>
<li>
<p><strong>Variety of destination</strong>: the co-ordination engine provides an extensible set of template types that can generate text to a variety of destinations. The next section describes the default template type, which is tailored to generate text to files on disk, while a subsequent section discusses the way in which users can define their own template types for generating text to other types of destination.</p>
</li>
<li>
<p><strong>Separation of concerns</strong>: the co-ordination engine ensures that the logic for controlling the text that is generated (i.e. the content) and the logic for controlling the way in which text is emitted (i.e. the destination) are kept separate.</p>
</li>
</ol>
<p>There is also the <a href="../egx/">EGX language</a>, which was introduced after this documentation was initially written, but provides a fully-fledged rule-based execution engine for paramterising EGL templates.</p>
<h3 id="the-template-type">The Template type<a class="headerlink" href="#the-template-type" title="Permanent link">&para;</a></h3>
<p>Central to the co-ordination engine is the <em>Template</em> type, which EGL provides in addition to the default EOL types. Via the <em>Template</em> type, EGL fulfils the three requirements identified above. Firstly, a <em>Template</em> can invoke other <em>Templates</em>, and hence can be shared and re-used between EGL programs. Secondly, the <em>Template</em> type has been implemented in an extensible manner: users can define their own types of <em>Template</em> that generate text to any destination (e.g. a database or a network socket), as described in the <a href="#customising-the-co-ordination-engine">custom coordination section</a>. Finally, the <em>Template</em> type provides a set of operations that are used to control the destination of generated text. Users typically define a "driver" template that does not generate text, but rather controls the destination of text that is generated by other templates.</p>
<p>For example, consider the EGL program in the listing below. This template generates no text (as it contains only a single dynamic section), but is used instead to control the destination of text generated by another template. Line 1 defines a variable, <code>t</code>, of type <em>Template</em>. Note that, unlike the EOL types, instances of <em>Template</em> are not created with the <code>new</code> keyword. Instead, the <em>TemplateFactory</em> built-in object is used to load templates from, for example, a file system path. On line 3, the <em>generate</em> operation of the <em>Template</em> type invokes the EGL template stored in the file "ClassNames.egl" and emits the generated text to "Output.txt".</p>
<pre class="prettyprint lang-egl"><code>[%
var t : Template = TemplateFactory.load("ClassNames.egl");
t.generate("Output.txt");
%]</code></pre>
<p>In addition to <code>generate</code>, the Template type defines further operations for controlling the context and invocation of EGL templates. The following table lists all of the operations defined on <em>Template</em>, and a further example of their use is given in the sequel.</p>
<table>
<thead>
<tr>
<th>Signature</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>populate(name : String, value : Any)</td>
<td>Makes a variable with the specified name and value available during the execution of the template.</td>
</tr>
<tr>
<td>process() : String</td>
<td>Executes the template and returns the text that is generated.</td>
</tr>
<tr>
<td>generate(destination : String)</td>
<td>Executes the template and stores the text to the specified destination. The format of the destination parameter is dictated by the type of template. For example, the default template type (which can generate files on disk) expects a file system path as the destination parameter. Returns a object representing the generated file.</td>
</tr>
<tr>
<td>append(destination : String)</td>
<td>Executes the template: if the destination exists, it will add a newline and the generated text at the end of the file. If the file does not exist, it will write the generated text to it (with no newline). Returns a object representing the generated file.</td>
</tr>
<tr>
<td>setFormatter(formatter : Formatter)</td>
<td>Changes the formatter for this template to the specified formatter. Subsequent calls to generate or process will produce text that is formatted with the specified formatter.</td>
</tr>
<tr>
<td>setFormatters(formatters : Sequence(Formatter))</td>
<td>Changes the formatter for this template to the specified sequence of formatters. Subsequent calls to generate or process will produce text that is formatted with each of the specified formatters in turn.</td>
</tr>
</tbody>
</table>
<h3 id="the-templatefactory-object">The TemplateFactory object<a class="headerlink" href="#the-templatefactory-object" title="Permanent link">&para;</a></h3>
<p>As discussed above, instances of <em>Template</em> are not created with the <code>new</code> keyword. Instead, EGL provides a built-in object, the <em>TemplateFactory</em>, for this purpose. Users can customise the type of the <em>TemplateFactory</em> object to gain more control over the way in which text is generated.</p>
<p>By default, EGL provides a <em>TemplateFactory</em> that exposes operations for loading templates (by loading files from disk), preparing templates (by parsing a string containing EGL code), and for controlling the file system locations from which templates are loaded and to which text is generated.</p>
<p>The table below lists the operations provided by the built-in <em>TemplateFactory</em> object.</p>
<table>
<thead>
<tr>
<th>Signature</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>load(path : String) : Template</td>
<td>Returns an instance of <em>Template</em> that can be used to execute the EGL template stored at the specified path.</td>
</tr>
<tr>
<td>prepare(code : String)</td>
<td>Changes the default path that is used to resolve relative paths when generating files to disk. Subsequent calls to load and prepare will create templates that use the new path.</td>
</tr>
<tr>
<td>setOutputRoot(path : String)</td>
<td>Changes the default path that is used to resolve relative paths when generating files to disk. Subsequent calls to load and prepare will create templates that use the new path.</td>
</tr>
<tr>
<td>setTemplateRoot(path : String)</td>
<td>Changes the default path that is used to resolve relative paths when loading templates with the load operation. Subsequent calls to load will use the new path.</td>
</tr>
<tr>
<td>setDefaultFormatter(formatter : Formatter)</td>
<td>Changes the formatter for this template factory to the specified formatter. Templates that are constructed after this operation has been invoked will produce text that is, by default, formatted with the specified formatter.</td>
</tr>
<tr>
<td>setDefaultFormatters(format- ters : Sequence(Formatter))</td>
<td>Sequence(Formatter)) &amp; Changes the formatter for this template to the specified sequence of formatters. Templates that are constructed after this operation has been invoked will produce text that is, by default, formatted with each of the specified formatters in turn.</td>
</tr>
</tbody>
</table>
<h3 id="an-example-of-co-ordination-with-egl">An Example of Co-ordination with EGL<a class="headerlink" href="#an-example-of-co-ordination-with-egl" title="Permanent link">&para;</a></h3>
<p>The operations provided by the <em>TemplateFactory</em> object and <em>Template</em> type are demonstrated by the EGL program in the listing below. Lines 2-3 use operations on <em>TemplateFactory</em> to change the paths from which templates will be loaded (line 2) and to which generated files will be created (line 3). Line 5 demonstrates the use of the <code>prepare</code> operation for creating a template from EGL code. When the <code>interface</code> template is invoked, the EGL code passed to the <code>prepare</code> operation will be executed. Finally, line 9 (and line 12) illustrates the way in which the <code>populate</code> operation can be used to pass a value to a template before invoking it. Specifically, the interface and implementation templates can use a variable called <em>root</em>, which is populated by the driver template before invoking them.</p>
<pre class="prettyprint lang-egl"><code>[%
TemplateFactory.setTemplateRoot("/usr/franz/templates");
TemplateFactory.setOutputRoot("/tmp/output");
var interface : Template =
TemplateFactory.prepare("public interface [%=root.name] {}");
var implementation : Template =
TemplateFactory.load("Class2Impl.egl");
for (c in Class.all) {
interface.populate("root", c);
interface.generate("I" + c.name + ".java");
implementation.populate("root", c);
implementation.generate(c.name + ".java");
}
%]</code></pre>
<h3 id="customising-the-co-ordination-engine">Customising the Co-ordination Engine<a class="headerlink" href="#customising-the-co-ordination-engine" title="Permanent link">&para;</a></h3>
<p>EGL provides mechanisms for customising the co-ordination engine. Specifically, users can define and use their own <em>TemplateFactory</em>. In many cases, users need not customise the co-ordination engine, and can write transformations using the built-in <em>Template</em> type and <em>TemplateFactory</em> object. If, however, you need more control over the co-ordination process, the discussion in this section might be helpful. Specifically, a custom <em>TemplateFactory</em> is typically used to achieve one or more of the following goals:</p>
<ol>
<li>
<p>Provide additional mechanisms for constructing <em>Templates</em>. <strong>Example:</strong> facilitate the loading of templates from a database.</p>
</li>
<li>
<p>Enrich / change the behaviour of the built-in <em>Template</em> type. <strong>Example:</strong> change the way in which generated text is sent to its destination.</p>
</li>
<li>
<p>Observe or instrument the transformation process by, for instance, logging calls to the operations provided by the <em>Template</em> type of the <em>TemplateFactory</em> object. <strong>Example:</strong> audit or trace the transformation process.</p>
</li>
</ol>
<p>Customisation is achieved in two stages: implementing the custom <em>TemplateFactory</em> (and potentially a custom <em>Template</em>) in Java, and using the custom <em>TemplateFactory</em>.</p>
<h4 id="implementing-a-custom-templatefactory">Implementing a custom TemplateFactory<a class="headerlink" href="#implementing-a-custom-templatefactory" title="Permanent link">&para;</a></h4>
<p>A custom <em>TemplateFactory</em> is a subclass of <code>EglTemplateFactory</code>. Typically, a custom <em>TemplateFactory</em> is implemented by overriding one of the methods of <code>EglTemplateFactory</code>. For example, the <code>createTemplate</code> method is overriden to specify that a custom type of <em>Template</em> should be created by the <em>TemplateFactory</em>. Likewise, the <code>load</code> and <code>prepare</code> methods can be overriden to change the location from which <em>Template</em>s are constructed.</p>
<p>A custom <em>Template</em> is a subclass of <code>EglTemplate</code> or, most often, a subclass of <code>EglPersistentTemplate</code>. Again, customisation is typically achieved by overriding methods in the superclass, or by adding new methods. For example, to perform auditing activities whenever a template is used to generate text, the <code>doGenerate</code> method of <code>EglPersistentTemplate</code> is overriden.</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">org.eclipse.epsilon.egl.EglFileGeneratingTemplateFactory</span><span class="p">;</span>
<span class="kn">import</span> <span class="nn">org.eclipse.epsilon.egl.EglTemplate</span><span class="p">;</span>
<span class="kn">import</span> <span class="nn">org.eclipse.epsilon.egl.EglPersistentTemplate</span><span class="p">;</span>
<span class="kn">import</span> <span class="nn">org.eclipse.epsilon.egl.exceptions.EglRuntimeException</span><span class="p">;</span>
<span class="kn">import</span> <span class="nn">org.eclipse.epsilon.egl.execute.context.IEglContext</span><span class="p">;</span>
<span class="kn">import</span> <span class="nn">org.eclipse.epsilon.egl.spec.EglTemplateSpecification</span><span class="p">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CountingTemplateFactory</span>
<span class="kd">extends</span> <span class="n">EglFileGeneratingTemplateFactory</span> <span class="p">{</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="n">EglTemplate</span> <span class="nf">createTemplate</span><span class="p">(</span><span class="n">EglTemplateSpecification</span> <span class="n">spec</span><span class="p">)</span>
<span class="kd">throws</span> <span class="n">Exception</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">CountingTemplate</span><span class="p">(</span><span class="n">spec</span><span class="p">,</span>
<span class="n">context</span><span class="p">,</span>
<span class="n">getOutputRootOrRoot</span><span class="p">(),</span>
<span class="n">outputRootPath</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CountingTemplate</span>
<span class="kd">extends</span> <span class="n">EglPersistentTemplate</span> <span class="p">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">int</span> <span class="n">numberOfCallsToGenerate</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">public</span> <span class="nf">CountingTemplate</span><span class="p">(</span><span class="n">EglTemplateSpecification</span> <span class="n">spec</span><span class="p">,</span>
<span class="n">IEglContext</span> <span class="n">context</span><span class="p">,</span>
<span class="n">URI</span> <span class="n">outputRoot</span><span class="p">,</span>
<span class="n">String</span> <span class="n">outputRootPath</span><span class="p">)</span>
<span class="kd">throws</span> <span class="n">Exception</span> <span class="p">{</span>
<span class="kd">super</span><span class="p">(</span><span class="n">spec</span><span class="p">,</span> <span class="n">context</span><span class="p">,</span> <span class="n">outputRoot</span><span class="p">,</span> <span class="n">outputRootPath</span><span class="p">);</span>
<span class="p">}</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">doGenerate</span><span class="p">(</span><span class="n">File</span> <span class="n">file</span><span class="p">,</span>
<span class="n">String</span> <span class="n">targetName</span><span class="p">,</span>
<span class="kt">boolean</span> <span class="n">overwrite</span><span class="p">,</span>
<span class="kt">boolean</span> <span class="n">protectRegions</span><span class="p">)</span>
<span class="kd">throws</span> <span class="n">EglRuntimeException</span> <span class="p">{</span>
<span class="n">numberOfCallsToGenerate</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<h4 id="using-a-custom-templatefactory">Using a custom TemplateFactory<a class="headerlink" href="#using-a-custom-templatefactory" title="Permanent link">&para;</a></h4>
<p>When invoking an EGL program, the user may select a custom <em>TemplateFactory</em>. For example, the EGL development tools provide an Eclipse launch configuration that provides a tab named "Generated Text."On this tab, users can select a <em>TemplateFactory</em> (under the group called "Type of Template Factory"). Note that a <em>TemplateFactory</em> only appears on the launch configuration tab if it has been registered with EGL via an Eclipse extension. Similarly, the <a href="../workflow">workflow language</a> provided by Epsilon allows the specification of custom types of <em>TemplateFactory</em> via the <code>templateFactoryType</code> parameter.</p>
<h3 id="summary">Summary<a class="headerlink" href="#summary" title="Permanent link">&para;</a></h3>
<p>The co-ordination engine provided by EGL facilitates the construction of modular and re-usable M2T transformations and can be used to generate text to various types of destination. Furthermore, the logic for specifying the contents of generated text is kept separate from the logic for specifying the destination of generated text.</p>
<h2 id="merge-engine">Merge Engine<a class="headerlink" href="#merge-engine" title="Permanent link">&para;</a></h2>
<p>EGL provides language constructs that allow M2T transformations to designate regions of generated text as <em>protected</em>. Whenever an EGL program attempts to generate text, any protected regions that are encountered in the specified destination are preserved.</p>
<p>Within an EGL program, protected regions are specified with the <em>preserve(String, String, String, Boolean, String)</em> method on the <code>out</code> keyword. The first two parameters define the comment delimiters of the target language. The other parameters provide the name, enable-state and content of the protected region, as illustrated in the listing below.</p>
<pre class="prettyprint lang-egl"><code>[%=out.preserve("/*", "*/", "anId", true,
"System.out.println(foo);")
%]</code></pre>
<p>A protected region declaration may have many lines, and use many EGL variables in the contents definition. To enhance readability, EGL provides two additional methods on the <code>out</code> keyword: <em>startPreserve(String, String, String, Boolean)</em> and <code>stopPreserve</code>. The listing below uses these to generate a protected region.</p>
<pre class="prettyprint lang-egl"><code>[%=out.startPreserve("/*", "*/", "anId", true)%]
System.out.println(foo);
[%=out.stopPreserve()%]</code></pre>
<p>Because an EGL template may contain many protected regions, EGL also provides a separate method to set the target language generated by the current template, <em>setContentType(String)</em>. By default, EGL recognises Java, HTML, Perl and EGL as valid content types. An alternative configuration file can be used to specify further content types. Following a call to <code>setContentType</code>, the first two arguments to the <code>preserve</code> and <code>startPreserve</code> methods can be omitted, as shown in the listing below.</p>
<pre class="prettyprint lang-egl"><code>[% out.setContentType("Java"); %]
[%=out.preserve("anId", true, "System.out.println(foo);")%]</code></pre>
<p>Because some languages define more than one style of comment delimiter, EGL allows mixed use of the styles for <code>preserve</code> and <code>startPreserve</code> methods.</p>
<p>Once a content type has been specified, a protected region may also be declared entirely from a static section, using the syntax in the listing below.</p>
<pre class="prettyprint lang-egl"><code>[% out.setContentType("Java"); %]
// protected region anId [on|off] begin
System.out.println(foo);
// protected region anId end</code></pre>
<p>When a template that defines one or more protected regions is processed by the EGL execution engine, the target output destinations are examined and existing contents of any protected regions are preserved. If either the output generated by from the template or the existing contents of the target output destination contains protected regions, a merging process is invoked. The table below shows the default behaviour of EGL's merge engine.</p>
<table>
<thead>
<tr>
<th>Protected Regions in Generated</th>
<th>Protected Regions in Existing</th>
<th>Contents taken from</th>
</tr>
</thead>
<tbody>
<tr>
<td>On</td>
<td>On</td>
<td>Existing</td>
</tr>
<tr>
<td>On</td>
<td>Off</td>
<td>Generated</td>
</tr>
<tr>
<td>On</td>
<td>Absent</td>
<td>Generated</td>
</tr>
<tr>
<td>Off</td>
<td>On</td>
<td>Existing</td>
</tr>
<tr>
<td>Off</td>
<td>Off</td>
<td>Generated</td>
</tr>
<tr>
<td>Off</td>
<td>Absent</td>
<td>Generated</td>
</tr>
<tr>
<td>Absent</td>
<td>On</td>
<td>Neither (causes a warning)</td>
</tr>
<tr>
<td>Absent</td>
<td>Off</td>
<td>Neither (causes a warning)</td>
</tr>
</tbody>
</table>
<h2 id="formatters">Formatters<a class="headerlink" href="#formatters" title="Permanent link">&para;</a></h2>
<p>Often the text generated by a model-to-text transformation is not formatted in a desirable manner. Text generated with a model-to-text transformation might contain extra whitespace or inconsistent indentation. This is because controlling the formatting of generated text in a model-to-text transformation language can be challenging.</p>
<p>In a template-based model-to-text language, such as EGL, it can be difficult to know how best to format a transformation. On the one hand, the transformation must be readable and understandable, and on the other hand, the generated text must typically also be readable and understandable.</p>
<p>Conscientious developers apply various <em>conventions</em> to produce readable code. EGL encourages template developers to prioritise the readability of templates over the readability of generated text when writing EGL templates. For formatting generated text, EGL provides an extensible set of <em>formatters</em> that can be invoked during a model-to-text transformation.</p>
<h3 id="using-a-formatter">Using a Formatter<a class="headerlink" href="#using-a-formatter" title="Permanent link">&para;</a></h3>
<p>EGL provides several built-in formatters. Users can implement additional formatters. To use a formatter, invoke the <code>setFormatter</code> or <code>setFormatters</code> operation on an instance of the <em>Template</em> type. A formatter is a Java class that implements EGL's Formatter interface. From within an EGL program, formatters can be created using a Native (i.e. Java) type. The listing below demonstrates the use of a built-in formatter (XmlFormatter).</p>
<pre class="prettyprint lang-egl"><code>[%
var f = new Native("org.eclipse.epsilon.egl.formatter.language.XmlFormatter");
var t = TemplateFactory.load("generate_some_xml.egl");
t.setFormatter(f);
t.generate("formatted.xml");
%]</code></pre>
<p>To facilitate the re-use of a formatter with many templates, the <em>TemplateFactory</em> object provides the <code>setDefaultFormatter</code> and <code>setDefaultFormatters</code> operations. Templates that are loaded or prepared after a call to <code>setDefaultFormatter</code> or <code>setDefaultFormatters</code> will, by default, use the formatter(s) specified for the <em>TemplateFactory</em>. Note that setting the formatter on a template overwrite any formatter that may have been set on that template by the <em>TemplateFactory</em>.</p>
<p>The default formatters for an EGL program can also be set when invoking the program. For example, the EGL development tools provide an Eclipse launch configuration that provides a tab named "Generated Text." On this tab, users can configure one or more formatters which will be used as the default formatters for this EGL program. Note that custom formatters only appear on the launch configuration tab if they have been registered with EGL via an Eclipse extension. Similarly, the <a href="../workflow">workflow language</a> provided by Epsilon provides a <code>formatter</code> nested element that can be used to specify one or more default formatters.</p>
<h3 id="implementing-a-custom-formatter">Implementing a Custom Formatter<a class="headerlink" href="#implementing-a-custom-formatter" title="Permanent link">&para;</a></h3>
<p>Providing a user-defined formatter involves implementing the <code>Formatter</code> interface (in <code>org.eclipse.epsilon.egl.formatter</code>). For example, the listing below demonstrates a simple formatter that transforms all generated text to uppercase.</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">org.eclipse.epsilon.egl.formatter.Formatter</span><span class="p">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">UppercaseFormatter</span> <span class="kd">implements</span> <span class="n">Formatter</span> <span class="p">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">format</span><span class="p">(</span><span class="n">String</span> <span class="n">text</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">text</span><span class="p">.</span><span class="na">toUpperCase</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>The set of built-in formatters provided by EGL includes some partial implementations of the <code>Formatter</code> interface that can be re-used to simplify the implementation of custom formatters. For instance, the <code>LanguageFormatter</code> class can correct the indentation of a program written in most languages, when given a start and end regular expression.</p>
<p>Finally, an Eclipse extension point is provided for custom formatters. Providing an extension that conforms to the custom formatter extension point allows EGL to display the custom formatter in the launch configuration tabs of the EGL development tools.</p>
<h2 id="traceability">Traceability<a class="headerlink" href="#traceability" title="Permanent link">&para;</a></h2>
<p>EGL also provides a traceability API, as a debugging aid, to support auditing of the M2T transformation process, and to facilitate change propagation. This API facilitates exploration of the templates executed, files affected and protected regions processed during a transformation. The figure below shows sample output from the traceability API after execution of an EGL M2T transformation to generate Java code from an instance of an OO metamodel. The view shown is accessed via the ... menu in Eclipse. Traceability information can also be accessed programmatically, as demonstrated in the listing below.</p>
<p><img alt="Sample output from the traceability
API." src="../images/TraceView.png" /></p>
<div class="highlight"><pre><span></span><code><span class="n">EglTemplateFactoryModuleAdapter</span> <span class="n">module</span> <span class="o">=</span>
<span class="k">new</span> <span class="n">EglTemplateFactoryModuleAdapter</span><span class="p">(</span><span class="k">new</span> <span class="n">EglTemplateFactory</span><span class="p">());</span>
<span class="kt">boolean</span> <span class="n">parsed</span> <span class="o">=</span> <span class="n">module</span><span class="p">.</span><span class="na">parse</span><span class="p">(</span><span class="k">new</span> <span class="n">File</span><span class="p">(</span><span class="s">&quot;myTemplate.egl&quot;</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">parsed</span> <span class="o">&amp;&amp;</span> <span class="n">module</span><span class="p">.</span><span class="na">getParseProblems</span><span class="p">().</span><span class="na">isEmpty</span><span class="p">())</span> <span class="p">{</span>
<span class="n">module</span><span class="p">.</span><span class="na">execute</span><span class="p">();</span>
<span class="n">Template</span> <span class="n">base</span> <span class="o">=</span> <span class="n">module</span><span class="p">.</span><span class="na">getContext</span><span class="p">().</span><span class="na">getBaseTemplate</span><span class="p">();</span>
<span class="c1">// traverse the template hierachy</span>
<span class="c1">// display data </span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// error handling</span>
<span class="p">}</span>
</code></pre></div>
<h2 id="additional-resources">Additional Resources<a class="headerlink" href="#additional-resources" title="Permanent link">&para;</a></h2>
<p>Additional resources about EGL/EGX are available <a href="../articles/#epsilon-generation-language">here</a>.</p>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../eol/" title="Object Language (EOL)" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Object Language (EOL)
</span>
</div>
</a>
<a href="../evl/" title="Model Validation (EVL)" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Model Validation (EVL)
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
<div class="md-footer-copyright__highlight">
Copyright © Eclipse Foundation, Inc. All Rights Reserved.
</div>
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">Material for MkDocs</a>
</div>
<div class="md-footer-copyright epsilon-eclipse-links">
<ul>
<li><a href="https://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="https://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="https://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
</ul>
</div>
<div class="md-footer-social">
<a href="https://twitter.com/eclipseepsilon" target="_blank" rel="noopener" title="twitter.com" class="md-footer-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
</a>
<a href="https://youtube.com/epsilondevs" target="_blank" rel="noopener" title="youtube.com" class="md-footer-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": [], "translations": {"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.term.missing": "Missing"}, "search": "../../assets/javascripts/workers/search.d351de03.min.js", "version": null}</script>
<script src="../../assets/javascripts/bundle.a1609d9a.min.js"></script>
<script src="https://unpkg.com/mermaid@8.5.1/dist/mermaid.min.js"></script>
<script src="../../assets/javascript/mermaid.js"></script>
<script src="../../assets/javascript/jquery.js"></script>
<script src="../../assets/javascript/slick.min.js"></script>
<script src="../../assets/javascript/google-code-prettify/prettify.js"></script>
<script src="../../assets/javascript/google-code-prettify/lang-emfatic.js"></script>
<script src="../../assets/javascript/google-code-prettify/lang-epsilon.js"></script>
<script src="../../assets/javascript/google-code-prettify/prettyprint.js"></script>
<script src="../../assets/javascript/extra.js"></script>
<script src="https://w.appzi.io/w.js?token=jlv6W"></script>
</body>
</html>