blob: 62e6a334209c9870b6f19c4dccecf64d198580d3 [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>Wizard Language (EWL) - 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-wizard-language-ewl" 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">
Wizard Language (EWL)
</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">
<a href="../egl/" class="md-nav__link">
Code Generation (EGL)
</a>
</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 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">
Wizard Language (EWL)
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
Wizard Language (EWL)
</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="#motivation" class="md-nav__link">
Motivation
</a>
<nav class="md-nav" aria-label="Motivation">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#automating-the-construction-and-refactoring-process" class="md-nav__link">
Automating the Construction and Refactoring Process
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#update-transformations-in-the-small" class="md-nav__link">
Update Transformations in the Small
</a>
<nav class="md-nav" aria-label="Update Transformations in the Small">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#structure-of-wizards" class="md-nav__link">
Structure of Wizards
</a>
</li>
<li class="md-nav__item">
<a href="#capabilities-of-wizards" class="md-nav__link">
Capabilities of Wizards
</a>
</li>
</ul>
</nav>
</li>
<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>
</li>
<li class="md-nav__item">
<a href="#execution-semantics" class="md-nav__link">
Execution Semantics
</a>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
Examples
</a>
<nav class="md-nav" aria-label="Examples">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#converting-a-class-into-a-singleton" class="md-nav__link">
Converting a Class into a Singleton
</a>
</li>
<li class="md-nav__item">
<a href="#renaming-a-class" class="md-nav__link">
Renaming a Class
</a>
</li>
<li class="md-nav__item">
<a href="#moving-model-elements-into-a-different-package" class="md-nav__link">
Moving Model Elements into a Different Package
</a>
</li>
</ul>
</nav>
</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_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="#motivation" class="md-nav__link">
Motivation
</a>
<nav class="md-nav" aria-label="Motivation">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#automating-the-construction-and-refactoring-process" class="md-nav__link">
Automating the Construction and Refactoring Process
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#update-transformations-in-the-small" class="md-nav__link">
Update Transformations in the Small
</a>
<nav class="md-nav" aria-label="Update Transformations in the Small">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#structure-of-wizards" class="md-nav__link">
Structure of Wizards
</a>
</li>
<li class="md-nav__item">
<a href="#capabilities-of-wizards" class="md-nav__link">
Capabilities of Wizards
</a>
</li>
</ul>
</nav>
</li>
<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>
</li>
<li class="md-nav__item">
<a href="#execution-semantics" class="md-nav__link">
Execution Semantics
</a>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
Examples
</a>
<nav class="md-nav" aria-label="Examples">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#converting-a-class-into-a-singleton" class="md-nav__link">
Converting a Class into a Singleton
</a>
</li>
<li class="md-nav__item">
<a href="#renaming-a-class" class="md-nav__link">
Renaming a Class
</a>
</li>
<li class="md-nav__item">
<a href="#moving-model-elements-into-a-different-package" class="md-nav__link">
Moving Model Elements into a Different Package
</a>
</li>
</ul>
</nav>
</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-wizard-language-ewl">The Epsilon Wizard Language (EWL)<a class="headerlink" href="#the-epsilon-wizard-language-ewl" title="Permanent link">&para;</a></h1>
<p>There are two types of model-to-model transformations: mapping and update transformations. Mapping transformations typically transform a source model into a set of target models expressed in (potentially) different modelling languages by creating zero or more model elements in the target models for each model element of the source model. By contrast, update transformations perform in-place modifications in the source model itself. They can be further classified into two subcategories: transformations in the small and in the large. Update transformations in the large apply to sets of model elements calculated using well-defined rules in a batch manner. An example of this category of transformations is a transformation that automatically adds accessor and mutator operations for all attributes in a UML model. On the other hand, update transformations in the small are applied in a user-driven manner on model elements that have been explicitly selected by the user. An example of this kind of transformations is a transformation that renames a <em>user-specified</em> UML class and all its incoming associations consistently.</p>
<p>In Epsilon, mapping transformations can be specified using <a href="../etl">ETL</a>, and update transformations in the large can be implemented either using the model modification features of EOL or using an ETL transformation in which the source and target models are the same model. By contrast, update transformations in the small cannot be effectively addressed by any of the languages presented so far.</p>
<p>The following section discusses the importance of update transformations in the small and motivates the definition of a task-specific language (Epsilon Wizard Language (EWL)) that provides tailored and effective support for defining and executing update transformations on models of diverse metamodels.</p>
<h2 id="motivation">Motivation<a class="headerlink" href="#motivation" title="Permanent link">&para;</a></h2>
<p>Constructing and refactoring models is undoubtedly a mentally intensive process. However, during modelling, recurring patterns of model update activities typically appear. As an example, when renaming a class in a UML class diagram, the user also needs to manually update the names of association ends that link to the renamed class. Thus, when renaming a class from <em>Chapter</em> to <em>Section</em>, all associations ends that point to the class and are named <em>chapter</em> or <em>chapters</em> should be also renamed to <em>section</em> and <em>sections</em> respectively. As another example, when a modeller needs to refactor a UML class into a singleton [@Larman], they need to go through a number of well-defined, but trivial, steps such as attaching a stereotype (<code>&lt;&lt;singleton&gt;&gt;</code>), defining a static <em>instance</em> attribute and adding a static <em>getInstance()</em> method that returns the unique instance of the singleton.</p>
<p>It is generally accepted that performing repetitive tasks manually is both counter-productive and error-prone. On the other hand, failing to complete such tasks correctly and precisely compromises the consistency, and thus the quality, of the models. In Model Driven Engineering, this is particularly important since models are increasingly used to automatically produce (parts of) working systems.</p>
<h3 id="automating-the-construction-and-refactoring-process">Automating the Construction and Refactoring Process<a class="headerlink" href="#automating-the-construction-and-refactoring-process" title="Permanent link">&para;</a></h3>
<p>Contemporary modelling tools provide built-in transformations (<em>wizards</em>) for automating common repetitive tasks. However, according to the architecture of the designed system and the specific problem domain, additional repetitive tasks typically appear, which cannot be addressed by the pre-conceived built-in wizards of a modelling tool. To address the automation problem in its general case, users must be able to easily define update transformations (wizards) that are tailored to their specific needs.</p>
<p>To an extent, this can be achieved via the extensible architecture that state-of-the-art modelling tools often provide which enables users to add functionality to the tool via scripts or application code using the implementation language of the tool. Nevertheless, the majority of modelling tools provide an API through which they expose an edited model, which requires significant effort to learn and use. Also, since each API is proprietary, such scripts and extensions are not portable to other tools. Finally, API scripting languages and third-generation languages such as Java and C++ are not particularly suitable for model navigation and modification.</p>
<p>Furthermore, existing languages for mapping transformations, such as QVT, ATL and ETL, cannot be used as-is for this purpose, because these languages have been designed to operate in a batch manner without human involvement in the process. By contrast, as discussed above, the task of constructing and refactoring models is inherently user-driven.</p>
<h2 id="update-transformations-in-the-small">Update Transformations in the Small<a class="headerlink" href="#update-transformations-in-the-small" title="Permanent link">&para;</a></h2>
<p>Update transformations are actions that automatically create, update or delete model elements based on a selection of existing elements in the model and information obtained otherwise (e.g. through user input), in a user-driven fashion. In this section, such actions are referred to as <em>wizards</em> instead of <em>rules</em> to reduce confusion between them and rules of mapping transformation languages. In the following sections, the desirable characteristics of wizards are elaborated informally.</p>
<h3 id="structure-of-wizards">Structure of Wizards<a class="headerlink" href="#structure-of-wizards" title="Permanent link">&para;</a></h3>
<p>In its simplest form, a wizard only needs to define the actions it will perform when it is applied to a selection of model elements. The structure of such a wizard that transforms a UML class into a <em>singleton</em> is shown using pseudo-code in the listing below.</p>
<div class="highlight"><pre><span></span><code>do :
attach the singleton stereotype
create the instance attribute
create the getInstance method
</code></pre></div>
<p>Since not all wizards apply to all types of elements in the model, each wizard needs to specify the types of elements to which it applies. For example, the wizard of the listing above, which automatically transforms a class into a singleton, applies only when the selected model element is a class. The simplest approach to ensuring that the wizard will only be applied on classes is to enclose its body in an <em>if</em> condition as shown in the listing below.</p>
<div class="highlight"><pre><span></span><code>do :
if (selected element is a class) {
attach the singleton stereotype
create the instance attribute
create the getInstance method
}
</code></pre></div>
<p>A more modular approach is to separate this condition from the body of the wizard. This is shown in the listing below where the condition of the wizard is specified as a separate <em>guard</em> stating that the wizard applies only to elements of type Class. The latter is preferable since it enables filtering out wizards that are not applicable to the current selection of elements by evaluating only their <em>guard</em> parts and rejecting those that return <em>false</em>. Thus, at any time, the user can be provided with only the wizards that are applicable to the current selection of elements. Filtering out irrelevant wizards reduces confusion and enhances usability, particularly as the list of specified wizards grows.</p>
<div class="highlight"><pre><span></span><code>guard : selected element is a class
do :
attach the singleton stereotype
create the instance attribute
create the getInstance method
</code></pre></div>
<p>To enhance usability, a wizard also needs to define a short human-readable description of its functionality. To achieve this, another field named <em>title</em> has been added. There are two options for defining the title of a wizard: the first is to use a static string and the second to use a dynamic expression. The latter is preferable since it enables definition of context-aware titles.</p>
<div class="highlight"><pre><span></span><code>guard : selected element is a class
title : Convert class &lt;class-name&gt; into a singleton
do :
attach the singleton stereotype
create the instance attribute
create the getInstance method
</code></pre></div>
<h3 id="capabilities-of-wizards">Capabilities of Wizards<a class="headerlink" href="#capabilities-of-wizards" title="Permanent link">&para;</a></h3>
<p>The <em>guard</em> and <em>title</em> parts of a wizard need to be expressed using a language that provides model querying and navigation facilities. Moreover, the <em>do</em> part also requires model modification capabilities to implement the transformation. To achieve complex transformations, it is essential that the user can provide additional information. For instance, to implement a wizard that addresses the class renaming scenario, the information provided by the selected class does not suffice; the user must also provide the new name of the class. Therefore, EWL must also provide mechanisms for capturing user input.</p>
<h2 id="abstract-syntax">Abstract Syntax<a class="headerlink" href="#abstract-syntax" title="Permanent link">&para;</a></h2>
<p>Since EWL is built atop Epsilon, its abstract and concrete syntax need only to define the concepts that are relevant to the task it addresses; they can reuse lower-level constructs from EOL. A graphical overview of the abstract syntax of the language is provided in the figure below.</p>
<p>The basic concept of the EWL abstract syntax is a <em>Wizard</em>. A wizard defines a <em>name</em>, a <em>guard</em> part, a <em>title</em> part and a $do$ part. Wizards are organized in <em>Modules</em>. The <em>name</em> of a wizard acts as an identifier and must be unique in the context of a module. The <em>guard</em> and <em>title</em> parts of a wizard are of type <em>ExpressionOrStatementBlock</em>, inherited from EOL. An <em>ExpressionOrStatementBlock</em> is either a single EOL expression or a block of EOL statements that include one or more <em>return</em> statements. This construct allows users to express simple declarative calculations as single expressions and complex calculations as blocks of imperative statements. Finally, the <em>do</em> part of the wizard is a block of EOL statements that specify the effects of the wizard when applied to a compatible selection of model elements.</p>
<p><img alt="EWL Abstract
Syntax" src="../images/EwlAbstractSyntax.png" /></p>
<h2 id="concrete-syntax">Concrete Syntax<a class="headerlink" href="#concrete-syntax" title="Permanent link">&para;</a></h2>
<p>The following listing presents the concrete syntax of EWL wizards.</p>
<div class="highlight"><pre><span></span><code>wizard &lt;name&gt; {
(guard (:expression)|({statementBlock}))?
(title (:expression)|({statementBlock}))?
do {
statementBlock
}
}
</code></pre></div>
<h2 id="execution-semantics">Execution Semantics<a class="headerlink" href="#execution-semantics" title="Permanent link">&para;</a></h2>
<p>The process of executing EWL wizards is inherently user-driven and as such it depends on the environment in which they are used. In general, each time the selection of model elements changes (i.e. the user selects or deselects a model element in the modelling tool), the guards of all wizards are evaluated. If the guard of a wizard is satisfied, the <em>title</em> part is also evaluated and the wizard is added to a list of <em>applicable</em> wizards. Then, the user can select a wizard and execute its <em>do</em> part to perform the intended transformation.</p>
<p>In EWL, variables defined and initialized in the <em>guard</em> part of the wizard can be accessed both by the <em>title</em> and the <em>do</em> parts. In this way, results of calculations performed in the <em>guard</em> part can be re-used, instead of re-calculated in the subsequent parts. The practicality of this approach is discussed in more detail in the examples that follow. Also, the execution of the <em>do</em> part of each wizard is performed in a transactional mode by exploiting the transaction capabilities of the underlying model connectivity framework, so that possible logical errors in the <em>do</em> part of a wizard do not leave the edited model in an inconsistent state.</p>
<h2 id="examples">Examples<a class="headerlink" href="#examples" title="Permanent link">&para;</a></h2>
<p>This section presents three concrete examples of EWL wizards for refactoring UML 1.4 models. The aim of this section is not to provide complete implementations that address all the sub-cases of each scenario but to provide enhanced understanding of the concrete syntax, the features and the capabilities of EWL to the reader. Moreover, it should be stressed again that although the examples in this section are based on UML models, by building on Epsilon, EWL can be used to capture wizards for diverse modelling languages and technologies.</p>
<h3 id="converting-a-class-into-a-singleton">Converting a Class into a Singleton<a class="headerlink" href="#converting-a-class-into-a-singleton" title="Permanent link">&para;</a></h3>
<p>The singleton pattern is applied when there is a class for which only one instance can exist at a time. In terms of UML, a singleton is a class stereotyped with the <code>&lt;&lt;singleton&gt;&gt;</code> stereotype, and it defines a static attribute named <code>instance</code> which holds the value of the unique instance. It also defines a static <code>getInstance()</code> operation that returns that unique instance. Wizard <code>ClassToSingleton</code>, presented below, simplifies the process of converting a class into a singleton by adding the proper stereotype, attribute and operation to it automatically.</p>
<div class="highlight"><pre><span></span><code>wizard ClassToSingleton {
// The wizard applies when a class is selected
guard : self.isTypeOf(Class)
title : &quot;Convert &quot; + self.name + &quot; to a singleton&quot;
do {
// Create the getInstance() operation
var gi : new Operation;
gi.owner = self;
gi.name = &quot;getInstance&quot;;
gi.visibility = VisibilityKind#vk_public;
gi.ownerScope = ScopeKind#sk_classifier;
// Create the return parameter of the operation
var ret : new Parameter;
ret.type = self;
ret.kind = ParameterDirectionKind#pdk_return;
gi.parameter = Sequence{ret};
// Create the instance field
var ins : new Attribute;
ins.name = &quot;instance&quot;;
ins.type = self;
ins.visibility = VisibilityKind#vk_private;
ins.ownerScope = ScopeKind#sk_classifier;
ins.owner = self;
// Attach the &lt;&lt;singleton&gt;&gt; stereotype
self.attachStereotype(&quot;singleton&quot;);
}
}
// Attaches a stereotype with the specified name
// to the Model Element on which it is invoked
operation ModelElement attachStereotype(name : String) {
var stereotype : Stereotype;
// Try to find an existing stereotype with this name
stereotype = Stereotype.allInstances.selectOne(s|s.name = name);
// If there is no existing stereotype
// with that name, create one
if (not stereotype.isDefined()){
stereotype = Stereotype.createInstance();
stereotype.name = name;
stereotype.namespace = self.namespace;
}
// Attach the stereotype to the model element
self.stereotype.add(stereotype);
}
</code></pre></div>
<p>The <code>guard</code> part of the wizard specifies that it is only applicable when the selection is a single UML class. The <code>title</code> part specifies a context-aware title that informs the user of the functionality of the wizard and the <code>do</code> part implements the functionality by adding the <code>getInstance</code> operation (lines 10-14), the <code>instance</code> attribute (lines 23-28) and the <code>&lt;&lt;singleton&gt;&gt;</code> stereotype (line 31). </p>
<p>The stereotype is added via a call to the <code>attachStereotype()</code> operation. Attaching a stereotype is a very common action when refactoring UML models, particularly where UML profiles are involved, and therefore to avoid duplication, this reusable operation that checks for an existing stereotype, creates it if it does not already exists, and attaches it to the model element on which it is invoked has been specified.</p>
<p>An extended version of this wizard could also check for existing association ends that link to the class and for which the upper-bound of their multiplicity is greater than one and either disallow the wizard from executing on such classes (in the <code>guard</code> part) or update the upper-bound of their multiplicities to one (in the <code>do</code> part). However, the aim of this section is not to implement complete wizards that address all sub-cases but to provide a better understanding of the concrete syntax and the features of EWL. This principle also applies to the examples presented in the sequel.</p>
<h3 id="renaming-a-class">Renaming a Class<a class="headerlink" href="#renaming-a-class" title="Permanent link">&para;</a></h3>
<p>The most widely used convention for naming attributes and association
ends of a given class is to use a lower-case version of the name of the
class as the name of the attribute or the association end. For instance,
the two ends of a one-to-many association that links classes <code>Book</code> and
<code>Chapter</code> are most likely to be named <code>book</code> and <code>chapters</code>
respectively. When renaming a class (e.g. from <code>Chapter</code> to <code>Section</code>)
the user must then manually traverse the model to find all attributes
and association ends of this type and update their names (i.e. from
<code>chapter</code> or <code>bookChapter</code> to <code>section</code> and <code>bookSection</code> respectively).
This can be a daunting process especially in the context of large
models. Wizard <code>RenameClass</code> presented in the listing below automates this process.</p>
<div class="highlight"><pre><span></span><code>wizard RenameClass {
// The wizard applies when a Class is selected
guard : self.isKindOf(Class)
title : &quot;Rename class &quot; + self.name
do {
var newName : String;
// Prompt the user for the new name of the class
newName = UserInput.prompt(&quot;New name for class &quot; + self.name);
if (newName.isDefined()) {
var affectedElements : Sequence;
// Collect the AssociationEnds and Attributes
// that are affected by the rename
affectedElements.addAll(
AssociationEnd.allInstances.select(ae|ae.participant=self));
affectedElements.addAll(
Attribute.allInstances.select(a|a.type = self));
var oldNameToLower : String;
oldNameToLower = self.name.firstToLowerCase();
var newNameToLower : String;
newNameToLower = newName.firstToLowerCase();
// Update the names of the affected AssociationEnds
// and Attributes
for (ae in affectedElements) {
ae.replaceInName(oldNameToLower, newNameToLower);
ae.replaceInName(self.name, newName);
}
self.name = newName;
}
}
}
// Renames the ModelElement on which it is invoked
operation ModelElement replaceInName
(oldString : String, newString : String) {
if (oldString.isSubstringOf(self.name)) {
// Calculate the new name
var newName : String;
newName = self.name.replace(oldString, newString);
// Prompt the user for confirmation of the rename
if (UserInput.confirm
(&quot;Rename &quot; + self.name + &quot; to &quot; + newName + &quot;?&quot;)) {
// Perform the rename
self.name = newName;
}
}
}
</code></pre></div>
<p>As with the <code>ClassToSingleton</code> wizard, the <code>guard</code> part of <code>RenameClass</code> specifies that the wizard is applicable only when the selection is a simple class and the <em>title</em> provides a context-aware description of the functionality of the wizard.</p>
<p>The information provided by the selected class itself does not suffice in the case of renaming since the new name of the class is not specified anywhere in the existing model. In EWL, and in all languages that build on EOL, user input can be obtained using the built-in <code>UserInput</code> facility. Thus, in line 12 the user is prompted for the new name of the class using the <code>UserInput.prompt()</code> operation. Then, all the association ends and attributes that refer to the class are collected in the <code>affectedElements</code> sequence (lines 14-21). Using the <code>replaceInName</code> operation (lines 31 and 32), the name of each one is examined for a substring of the upper-case or the lower-case version of the old name of the class. In case the check returns true, the user is prompted to confirm (line 48) that the feature needs to be renamed. This further highlights the importance of user input for implementing update transformations with fine-grained user control.</p>
<h3 id="moving-model-elements-into-a-different-package">Moving Model Elements into a Different Package<a class="headerlink" href="#moving-model-elements-into-a-different-package" title="Permanent link">&para;</a></h3>
<p>A common refactoring when modelling in UML is to move model elements, particularly Classes, between different packages. When moving a pair of classes from one package to another, the associations that connect them must also be moved to the target package. To automate this process, the listing below presents the <code>MoveToPackage</code> wizard.</p>
<div class="highlight"><pre><span></span><code>wizard MoveToPackage {
// The wizard applies when a Collection of
// elements, including at least one Package
// is selected
guard {
var moveTo : Package;
if (self.isKindOf(Collection)) {
moveTo = self.select(e|e.isKindOf(Package)).last();
}
return moveTo.isDefined();
}
title : &quot;Move &quot; + (self.size()-1) + &quot; elements to &quot; + moveTo.name
do {
// Move the selected Model Elements to the
// target package
for (me in self.excluding(moveTo)) {
me.namespace = moveTo;
}
// Move the Associations connecting any
// selected Classes to the target package
for (a in Association.allInstances) {
if (a.connection.forAll(c|self.includes(c.participant))){
a.namespace = moveTo;
}
}
}
}
</code></pre></div>
<p>The wizard applies when more than one element is selected and at least one of the elements is a <em>Package</em>. If more than one package is selected, the last one is considered as the target package to which the rest of the selected elements will be moved. This is specified in the <em>guard</em> part of the wizard.</p>
<p>To reduce user confusion in identifying the package to which the elements will be moved, the name of the target package appears in the title of the wizard. This example shows the importance of the decision to express the title as a dynamically calculated expression (as opposed to a static string). It is worth noting that in the <em>title</em> part of the wizard (line 14), the <em>moveTo</em> variable declared in the <em>guard</em> (line 7) is referenced. Through experimenting with a number of wizards, it has been noticed that in complex wizards repeated calculations need to be performed in the <em>guard</em>, <em>title</em> and <em>do</em> parts of the wizard. To eliminate this duplication, the scope of variables defined in the <em>guard</em> part has been extended so that they are also accessible from the <em>title</em> and <em>do</em> part of the wizard.</p>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../pinset/" title="Dataset Extraction (Pinset)" 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>
Dataset Extraction (Pinset)
</span>
</div>
</a>
<a href="../picto/" title="Picto" 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>
Picto
</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>