blob: 461f408ae3974897b6ed906f628cf078bdcf690c [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="shortcut icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.1.2, mkdocs-material-5.4.0">
<title>Model migration (Flock) - Epsilon</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.fe0cca5b.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.a46bcfb3.min.css">
<meta name="theme-color" content="">
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
<style>body,input{font-family:"Roboto",-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono",SFMono-Regular,Consolas,Menlo,monospace}</style>
<link rel="stylesheet" href="../../assets/stylesheets/extra.css">
<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">
<!-- FAVICON -->
<link rel="apple-touch-icon" sizes="76x76" href="/assets/images/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="shortcut icon" href="/assets/images/favicon.ico">
</head>
<body dir="ltr" data-md-color-scheme="" data-md-color-primary="black" data-md-color-accent="orange">
<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="#epsilon-flock-for-model-migration" 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-nav md-grid" aria-label="Header">
<a href="../.." title="Epsilon" class="md-header-nav__button md-logo" aria-label="Epsilon">
<img src="../../assets/images/epsilon-white-background.png" alt="logo">
</a>
<label class="md-header-nav__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-nav__title" data-md-component="header-title">
<div class="md-header-nav__ellipsis">
<span class="md-header-nav__topic md-ellipsis">
Epsilon
</span>
<span class="md-header-nav__topic md-ellipsis">
Model migration (Flock)
</span>
</div>
</div>
<label class="md-header-nav__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 0116 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 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.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">
<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 0116 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 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.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" data-md-component="search-reset" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41L17.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-nav__source">
<a href="https://git.eclipse.org/c/epsilon/org.eclipse.epsilon.git/" title="Go to repository" class="md-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.05L244 40.45a28.87 28.87 0 00-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 01-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 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-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="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">
<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">
<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.05L244 40.45a28.87 28.87 0 00-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 01-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 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-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="../.." title="Home" class="md-nav__link">
Home
</a>
</li>
<li class="md-nav__item">
<a href="../../download/" title="Download" class="md-nav__link">
Download
</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-3" type="checkbox" id="nav-3" checked>
<label class="md-nav__link" for="nav-3">
Documentation
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Documentation" data-md-level="1">
<label class="md-nav__title" for="nav-3">
<span class="md-nav__icon md-icon">
<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>
</span>
Documentation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../" title="Overview" class="md-nav__link">
Overview
</a>
</li>
<li class="md-nav__item">
<a href="../emc/" title="Model connectivity" 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-3-3" type="checkbox" id="nav-3-3" checked>
<label class="md-nav__link" for="nav-3-3">
Languages
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Languages" data-md-level="2">
<label class="md-nav__title" for="nav-3-3">
<span class="md-nav__icon md-icon">
<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>
</span>
Languages
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../eol/" title="Object language (EOL)" class="md-nav__link">
Object language (EOL)
</a>
</li>
<li class="md-nav__item">
<a href="../egl/" title="Code generation (EGL)" class="md-nav__link">
Code generation (EGL)
</a>
</li>
<li class="md-nav__item">
<a href="../evl/" title="Model validation (EVL)" class="md-nav__link">
Model validation (EVL)
</a>
</li>
<li class="md-nav__item">
<a href="../etl/" title="Model transformation (ETL)" class="md-nav__link">
Model transformation (ETL)
</a>
</li>
<li class="md-nav__item">
<a href="../ecl/" title="Model comparison (ECL)" class="md-nav__link">
Model comparison (ECL)
</a>
</li>
<li class="md-nav__item">
<a href="../eml/" title="Model merging (EML)" class="md-nav__link">
Model merging (EML)
</a>
</li>
<li class="md-nav__item">
<a href="../epl/" title="Pattern matching (EPL)" class="md-nav__link">
Pattern matching (EPL)
</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">
Model migration (Flock)
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 9h14V7H3v2m0 4h14v-2H3v2m0 4h14v-2H3v2m16 0h2v-2h-2v2m0-10v2h2V7h-2m0 6h2v-2h-2v2z"/></svg>
</span>
</label>
<a href="./" title="Model migration (Flock)" class="md-nav__link md-nav__link--active">
Model migration (Flock)
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon">
<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>
</span>
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>
</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="#example" class="md-nav__link">
Example
</a>
</li>
<li class="md-nav__item">
<a href="#limitations-and-scope" class="md-nav__link">
Limitations and Scope
</a>
<nav class="md-nav" aria-label="Limitations and Scope">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#limitations" class="md-nav__link">
Limitations
</a>
</li>
<li class="md-nav__item">
<a href="#scope" class="md-nav__link">
Scope
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../emg/" title="Model generation (EMG)" class="md-nav__link">
Model generation (EMG)
</a>
</li>
<li class="md-nav__item">
<a href="../eunit/" title="Unit testing (EUnit)" class="md-nav__link">
Unit testing (EUnit)
</a>
</li>
<li class="md-nav__item">
<a href="../pinset/" title="Dataset extraction (Pinset)" class="md-nav__link">
Dataset extraction (Pinset)
</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-3-4" type="checkbox" id="nav-3-4">
<label class="md-nav__link" for="nav-3-4">
Tools
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Tools" data-md-level="2">
<label class="md-nav__title" for="nav-3-4">
<span class="md-nav__icon md-icon">
<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>
</span>
Tools
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../picto/" title="Picto" class="md-nav__link">
Picto
</a>
</li>
<li class="md-nav__item">
<a href="../flexmi/" title="Flexmi" class="md-nav__link">
Flexmi
</a>
</li>
<li class="md-nav__item">
<a href="../eugenia/" title="Eugenia" class="md-nav__link">
Eugenia
</a>
</li>
<li class="md-nav__item">
<a href="../exeed/" title="Exeed" class="md-nav__link">
Exeed
</a>
</li>
<li class="md-nav__item">
<a href="../modelink/" title="Modelink" class="md-nav__link">
Modelink
</a>
</li>
<li class="md-nav__item">
<a href="../hutn/" title="HUTN" class="md-nav__link">
HUTN
</a>
</li>
<li class="md-nav__item">
<a href="../workflow/" title="Workflow (Ant tasks)" class="md-nav__link">
Workflow (Ant tasks)
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../articles/" title="Articles" class="md-nav__link">
Articles
</a>
</li>
<li class="md-nav__item">
<a href="../../examples/" title="Examples" class="md-nav__link">
Examples
</a>
</li>
<li class="md-nav__item">
<a href="https://www.youtube.com/epsilondevs" title="Screencasts" class="md-nav__link">
Screencasts
</a>
</li>
<li class="md-nav__item">
<a href="https://www.youtube.com/playlist?list=PLRwHao6Ue0YUecg7vEUQTrtySIWwrd_mI" title="Lectures" 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-3-9" type="checkbox" id="nav-3-9">
<label class="md-nav__link" for="nav-3-9">
Javadoc
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Javadoc" data-md-level="2">
<label class="md-nav__title" for="nav-3-9">
<span class="md-nav__icon md-icon">
<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>
</span>
Javadoc
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://download.eclipse.org/epsilon/2.2/javadoc/" title="Stable" class="md-nav__link">
Stable
</a>
</li>
<li class="md-nav__item">
<a href="https://download.eclipse.org/epsilon/interim-javadoc/" title="Interim" 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-4" type="checkbox" id="nav-4">
<label class="md-nav__link" for="nav-4">
Issues
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Issues" data-md-level="1">
<label class="md-nav__title" for="nav-4">
<span class="md-nav__icon md-icon">
<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>
</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" title="Report a new issue" 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" title="View open bugs" 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" title="View enhancement requests" 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" title="View issues resolved since the last stable release" 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" title="View all issues" 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-5" type="checkbox" id="nav-5">
<label class="md-nav__link" for="nav-5">
Community
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Community" data-md-level="1">
<label class="md-nav__title" for="nav-5">
<span class="md-nav__icon md-icon">
<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>
</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-5-1" type="checkbox" id="nav-5-1">
<label class="md-nav__link" for="nav-5-1">
Who is using Epsilon?
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Who is using Epsilon?" data-md-level="2">
<label class="md-nav__title" for="nav-5-1">
<span class="md-nav__icon md-icon">
<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>
</span>
Who is using Epsilon?
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../users/" title="Industry" class="md-nav__link">
Industry
</a>
</li>
<li class="md-nav__item">
<a href="../../users/education/" title="Education" class="md-nav__link">
Education
</a>
</li>
<li class="md-nav__item">
<a href="../../users/open-source/" title="Open-source projects" 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" title="Who is developing Epsilon?" 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/" title="Forum" class="md-nav__link">
Forum
</a>
</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">
Social Media
<span class="md-nav__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>
</span>
</label>
<nav class="md-nav" aria-label="Social Media" data-md-level="2">
<label class="md-nav__title" for="nav-5-4">
<span class="md-nav__icon md-icon">
<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>
</span>
Social Media
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://twitter.com/eclipseepsilon" title="Twitter" class="md-nav__link">
Twitter
</a>
</li>
<li class="md-nav__item">
<a href="https://youtube.com/epsilondevs" title="YouTube" class="md-nav__link">
YouTube
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../labs/" title="Epsilon Labs" class="md-nav__link">
Epsilon Labs
</a>
</li>
<li class="md-nav__item">
<a href="../../faq/" title="Frequently asked questions" class="md-nav__link">
Frequently asked questions
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../branding/" title="Branding" class="md-nav__link">
Branding
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon">
<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>
</span>
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>
</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="#example" class="md-nav__link">
Example
</a>
</li>
<li class="md-nav__item">
<a href="#limitations-and-scope" class="md-nav__link">
Limitations and Scope
</a>
<nav class="md-nav" aria-label="Limitations and Scope">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#limitations" class="md-nav__link">
Limitations
</a>
</li>
<li class="md-nav__item">
<a href="#scope" class="md-nav__link">
Scope
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<h1 id="epsilon-flock-for-model-migration">Epsilon Flock for Model Migration<a class="headerlink" href="#epsilon-flock-for-model-migration" title="Permanent link">&para;</a></h1>
<p>The aim of Epsilon Flock is to contribute <em>model migration</em> capabilities to Epsilon. Model migration is the process of updating models in response to metamodel changes. This section discusses the motivation for implementing Flock, introduces its syntax and execution semantics, and demonstrates the use of Flock with an example. Flock can be used to update models to a new version of their metamodel, or even to move from one modelling technology to another (e.g., from XML to EMF).</p>
<p>To illustrate the challenges of model migration, we use the example of metamodel evolution below. In the top figure, a <code>Component</code> comprises other <code>Component</code>s, <code>Connector</code>s and <code>Port</code>s. A <code>Connector</code> joins two <code>Port</code>s. <code>Connector</code>s are unidirectional, and hence define <code>to</code> and <code>from</code> references to <code>Port</code>. The original metamodel allows a <code>Connector</code> to start and end at the same <code>Port</code>, and the metamodel was evolved to prevent this, as shown in the bottom figure. <code>Port</code> was made abstract, and split into two subtypes, <code>InputPort</code> and <code>OutputPort</code>. The references between <code>Connector</code> and (the subtypes of) <code>Port</code> were renamed for consistency with the names of the subtypes.</p>
<div class="mermaid mermaid-50">classDiagram
class Component {
+subcomponents: Component[*]
+connectors: Connector[*]
+ports: Port[*]
}
class Port {
+name: String
+outgoing: Connector
+incoming: Connector
}
class Connector {
+name: String
+from: Port
+to: Port
}
Component *-- Connector: connectors *
Component *-- Component
Component *-- Port: ports *
Connector -- Port: from
Port -- Connector: to</div>
<div class="mermaid mermaid-80">classDiagram
class Component {
+subcomponents: Component[*]
+connectors: Connector[*]
+ports: Port[*]
}
class Port {
+name: String
+outgoing: Connector
+incoming: Connector
}
class Connector {
+name: String
+in: InPort
+out: OutPort
}
class InputPort {
+connector: Connector
}
class OutputPort {
+connector: Connector
}
Component *-- Connector: connectors *
Component *-- Component
Component *-- Port: ports *
InputPort --|&gt; Port: in
OutputPort --|&gt; Port: out
Connector -- InputPort
Connector -- OutputPort</div>
<p>Some models that conform to the original metamodel do not conform to the evolved metamodel. Specifically, models might not conform to the evolved metamodel because:</p>
<ol>
<li>
<p>They contain instances of <code>Port</code>, which is an abstract class in the evolved metamodel.</p>
</li>
<li>
<p>They contain instances of <code>Connector</code> that specify values for the features <code>to</code> and <code>from</code>, which are not defined for the <code>Connector</code> type in the evolved metamodel.</p>
</li>
<li>
<p>They contain instances of <code>Connector</code> that do not specify a value for the <code>in</code> and <code>out</code> features, which are mandatory for the <code>Connector</code> type in the evolved metamodel.</p>
</li>
</ol>
<p>Model migration can be achieved with a general-purpose model-to-model transformation using a language such as ETL. However, this typically involves writing a large amount of repetitive and redundant code. Flock reduces the amount of repetitive and redundant code needed to specify model migration by automatically copying from the original to the migrated model all of the model elements that conform to the evolved metamodel as described below.</p>
<div class="mermaid mermaid-100">classDiagram
class GuardedConstruct {
-guard: ExecutableBlock&lt;Boolean&gt;
}
class Deletion {
-originalType: String
-strict: Boolean
-cascade: Boolean
}
class Retyping {
-originalType: String
-strict: Boolean
-evolvedType: String
}
class PackageRetyping {
-originalType: String
-evolvedType: String
}
class PackageDeletion {
-originalType: String
}
class MigrateRule {
-originalType: String
-strict: Boolean
-ignoredFeatures: String[*]
-body: ExecutableBlock&lt;Void&gt;
}
FlockModule -- TypeMappingConstruct: typeMappings *
Deletion --|&gt; TypeMappingConstruct
TypeMappingConstruct &lt;|-- Retyping
TypeMappingConstruct &lt;|-- PackageDeletion
TypeMappingConstruct &lt;|-- PackageRetyping
MigrationRule --|&gt; GuardedConstruct
GuardedConstruct &lt;|-- TypeMappingConstruct
FlockModule -- MigrateRule: rules *
EolModule &lt;|-- ErlModule
ErlModule &lt;|-- FlockModule
Pre --|&gt; NamedStatementBlockRule
Post --|&gt; NamedStatementBlockRule
ErlModule -- Pre: pre *
ErlModule -- Post: post *</div>
<h2 id="abstract-syntax">Abstract Syntax<a class="headerlink" href="#abstract-syntax" title="Permanent link">&para;</a></h2>
<p>As illustrated in the figure above, Flock migration strategies are organised into individual modules (<code>FlockModule</code>). Flock modules inherit from EOL language constructs for specifying user-defined operations and for importing other (EOL and Flock) modules. Like the other rule-based of Epsilon, Flock modules may comprise any number of pre (post) blocks, which are executed before (after) all other constructs. Flock modules comprise any number of type mappings (<code>TypeMapping</code>) and rules (<code>Rule</code>). Type mappings operate on metamodel types (<code>Retyping</code> and <code>Deletion</code>) or on metamodel packages (<code>PackageRetyping</code> and <code>PackageDeletion</code>). Type mappings are applied to a type in the original metamodel (<code>originalType</code>) or to a package in the original metamodel (<code>originalPackage</code>) . Additionally, <code>Retyping</code>s apply to an evolved metamodel type (<code>evolvedType</code>) or package (<code>evolvedPackage</code>). Each rule has an original metamodel type (<code>originalType</code>), a <code>body</code> comprising a block of EOL statements, and zero or more <code>ignoredFeatures</code>. Type mappings and rules can optionally specify a <code>guard</code>, which is either an EOL statement or a block of EOL statements. Type mappings that operate on metamodel types and rules can be marked as <code>strict</code>.</p>
<h2 id="concrete-syntax">Concrete Syntax<a class="headerlink" href="#concrete-syntax" title="Permanent link">&para;</a></h2>
<p>The listing below demonstrates the concrete syntax of the Flock language constructs. All of the constructs begin with keyword(s) (<code>retype</code>, <code>retype package</code> <code>delete</code>, <code>delete package</code> or <code>migrate</code>), followed by the original metamodel type or package. Additionally, type mappings that operate on metamodel types and rules can be annotated with the <code>strict</code> modifier. The <code>delete</code> construct can be annotated with a <code>cascade</code> modifier. All constructs can have guards, which are specified using the <code>when</code> keyword.</p>
<p>Migrate rules can specify a list of features that conservative copy will ignore (<code>ignoring</code>), and a <code>body</code> containing a sequence of at least one EOL statement. Note that a migrate rule must have a list of ignored features, or a body, or both.</p>
<div class="highlight"><pre><span></span><code>(@strict)?
retype &lt;originalType&gt; to &lt;evolvedType&gt;
(when (:&lt;eolExpression&gt;)|({&lt;eolStatement&gt;+}))?
retype package &lt;originalPackage&gt; to &lt;evolvedPackage&gt;
(when (:&lt;eolExpression&gt;)|({&lt;eolStatement&gt;+}))?
(@strict)?
(@cascade)?
delete &lt;originalType&gt;
(when (:&lt;eolExpression&gt;)|({&lt;eolStatement&gt;+}))?
delete package &lt;originalPackage&gt;
(when (:&lt;eolExpression&gt;)|({&lt;eolStatement&gt;+}))?
(@strict)?
migrate &lt;originalType&gt;
(ignoring &lt;featureList&gt;)?
(when (:&lt;eolExpression&gt;)|({&lt;eolStatement&gt;+}))? {
&lt;eolStatement&gt;+
}
</code></pre></div>
<p><em>Pre</em> and <em>post</em> blocks have a simple syntax that, as presented below, consists of the identifier (<em>pre</em> or <em>post</em>), an optional name and the set of statements to be executed enclosed in curly braces.</p>
<div class="highlight"><pre><span></span><code>(pre|post) &lt;name&gt; {
statement+
}
</code></pre></div>
<h2 id="execution-semantics">Execution Semantics<a class="headerlink" href="#execution-semantics" title="Permanent link">&para;</a></h2>
<p>The execution semantics of a Flock module are now described. Note that the Epsilon Model Connectivity (EMC) layer, which Flock uses to access and manipulate models supports a range of modelling technologies, and identifies types by name. Consequently, the term <em>type</em> is used to mean "the name of an element of a metamodel" in the following discussion. For example, <code>Component</code>, <code>Connector</code> and <code>InputPort</code> are three of the types defined in the evolved metamodel.</p>
<p>Execution of a Flock module occurs in six phases:</p>
<ol>
<li>
<p>Any pre blocks are executed.</p>
</li>
<li>
<p>Type mapping constructs (retypings and deletions) are processed to identify the way in which original and evolved metamodel types are to be related.</p>
</li>
<li>
<p>Migrate rules are inspected to build sets of ignored properties.</p>
</li>
<li>
<p>The information determined in steps 2 and 3 is used as input a copying algorithm, which creates an (equivalent) element in the migrated model for each element of the original model, and copies values from original to equivalent model elements.</p>
</li>
<li>
<p>Migrate rules are executed on each pair of original and (equivalent) migrated model elements.</p>
</li>
<li>
<p>Any post blocks are executed.</p>
</li>
</ol>
<p>In phases 2-5, language constructs are executed only when they are <em>applicable</em>. The <em>applicability</em> of the Flock language constructs (retyping, deletion or migrate rule) is determined from their type and guard. For a language construct <code>c</code> to be applicable to an original model element <code>o</code>, <code>o</code> must instantiate either the original type of <code>c</code> or one of the subtypes of the original type of <code>c</code>; and <code>o</code> must satisfy the guard of <code>c</code>. For language constructs that have been annotated as strict, type-checking is more restrictive: <code>o</code> must instantiate the original type of <code>c</code> (and not one its subtypes). In other words, the applicability of strict constructs is determined with EOL's <code>isTypeOf</code> operation and the applicability of non-strict constructs is determined with EOL's <code>isKindOf</code> operation. For language constructs that have been annotated with cascade, type-checking is less restrictive: <code>o</code> must be contained in another model element (either directly or indirectly) to which the construct is applicable. Similarly, for language constructs that operate on packages (i.e. package retyping and package deletions), type-checking is less restrictive: <code>o</code> must be contained in a package with the same name as the original package of <code>c</code>.</p>
<p>Phases 2-4 of execution implement a copying algorithm which has been termed conservative copy and is discussed thoroughly <a href="https://link.springer.com/chapter/10.1007/978-3-642-16145-2_5">elsewhere</a>. Essentially, conservative copy will do the following for each element of the original model, <code>o</code>:</p>
<ol>
<li>
<p><strong>Do nothing</strong> when <code>o</code> instantiates a type that cannot be instantiated in the evolved metamodel (e.g., because the type of <code>o</code> is now abstract or no longer exists). Example: instances of <code>Port</code> in the original metamodel are not copied because <code>Port</code> has become abstract.</p>
</li>
<li>
<p><strong>Fully copy</strong> <code>o</code> to produce <code>m</code> in the migrated model when <code>o</code> instantiate a type that has not been at all affected by metamodel evolution. Example: instances of <code>Component</code> in the original metamodel are fully copied because neither <code>Component</code> nor any of its features have been changed.</p>
</li>
<li>
<p><strong>Partially copy</strong> <code>o</code> to produce <code>m</code> in the migrated model when <code>o</code> instantiates a type with one or more features that have been affected by metamodel evolution. Example: instances of <code>Connector</code> in the original metamodel are partially copied because the <code>from</code> and <code>to</code> features have been renamed. Note that in a partial copy only the features that have not been affected by metamodel evolution are copied (e.g., the <code>name</code>s of <code>Connector</code>s).</p>
</li>
</ol>
<p>In phase 5, migrate rules are applied. These rules specify the problem-specific migration logic and might, for example, create migrated model elements for original model elements that were skipped or partially copied by the copying algorithm described above. The Flock engine makes available two variables (<code>original</code> and <code>migrated</code>) for use in the body of any migration rule. These variables are used to refer to the particular elements of the original and migrated models to which the rule is currently being applied. In addition, Flock defines an <code>equivalent()</code> operation that can be called on any original model element and returns the equivalent migrated model element (or <code>null</code>). The <code>equivalent()</code> operation is used to access elements of the migrated model that cannot be accessed via the <code>migrated</code> variable due to metamodel evolution. Flock rules often contain statements of the form: <code>original.x.equivalent()</code> where <code>x</code> is a feature that has been removed from the evolved metamodel.</p>
<p>Finally, we should consider the order in which Flock schedules language constructs: a construct that appears earlier (higher) in the source file has priority. This is important because only one type mapping (retypings and deletions) is applied per original model element, and because this implies that migrate rules are applied from top-to-bottom. This ordering is consistent with the other languages of the Epsilon platform.</p>
<h2 id="example">Example<a class="headerlink" href="#example" title="Permanent link">&para;</a></h2>
<p>Flock is now demonstrated using the example of model migration
introduced above. Recall that the metamodel evolution
involves splitting the <code>Port</code> type to form the
<code>InputPort</code> and <code>OutputPort</code> types.
Below is a high-level design for
migrating models from the original to the evolved metamodel.</p>
<ul>
<li>
<p>For every instance, p, of <code>Port</code> in the original model: </p>
<ul>
<li>
<p>If there exists in the original model a <code>Connector</code>, c, that specifies p as
the value for its <code>from</code> feature:</p>
<ul>
<li>Create a new instance, <code>i</code>, of <code>InputPort</code> in the migrated model. </li>
<li>Set c as the <code>connector</code> of <code>i</code>. </li>
<li>Add c to the <code>ports</code> reference of the <code>Component</code> that contains c.</li>
</ul>
</li>
<li>
<p>If there exists in the original model a <code>Connector</code>, c, that specifies p as the value for its <code>to</code> feature: </p>
<ul>
<li>Create a new instance of <code>OutputPort</code> in the migrated model. </li>
<li>Set c as the <code>connector</code> of i. </li>
<li>Add c to the <code>ports</code> reference of the <code>Component</code> that contains c.</li>
</ul>
</li>
</ul>
</li>
<li>
<p>And nothing else changes.</p>
</li>
</ul>
<p>The Flock migration strategy that implements this design is shown below. Three type mappings constructs (on lines 1-4) are used to control the way in which instances of <code>Port</code> are migrated. For example, line 3 specifies that instances of <code>Port</code> that are referenced via the <code>from</code> feature of a <code>Connector</code> are retyped, becoming <code>InputPort</code>s. Instances of <code>Connector</code> are migrated using the rule on lines 6-9, which specifies the way in which the <code>from</code> and <code>to</code> features have evolved to form the <code>in</code> and <code>out</code> features.</p>
<pre class="prettyprint lang-mig"><code>delete Port when: not (original.isInput() xor original.isOutput())
retype Port to InputPort when: original.isInput()
retype Port to OutputPort when: original.isOutput()
migrate Connector {
migrated.`in` = original.from.equivalent();
migrated.out = original.`to`.equivalent();
}
operation Original!Port isInput() : Boolean {
return Original!Connector.all.exists(c|c.from == self);
}
operation Original!Port isOutput() : Boolean {
return Original!Connector.all.exists(c|c.`to` == self);
}</code></pre>
<p>Note that metamodel elements that have not been affected by the metamodel evolution, such as <code>Component</code>s, are migrated automatically. Explicit copying code would be needed to achieve this with a general purpose model-to-model transformation language.</p>
<h2 id="limitations-and-scope">Limitations and Scope<a class="headerlink" href="#limitations-and-scope" title="Permanent link">&para;</a></h2>
<p>Although Flock has been shown to much more concise than general purpose model-to-model transformation languages for specifying model migration, Flock does not provide some of the features commonly available in general-purpose model-to-model transformation language. This section discusses the limitations of Flock and its intended scope with respect to other tools for model migration.</p>
<h3 id="limitations">Limitations<a class="headerlink" href="#limitations" title="Permanent link">&para;</a></h3>
<p>Firstly, Flock does not support rule inheritance, and re-use of migration logic is instead achieved by exploiting the inheritance hierarchy of the original metamodel. The form of re-use provided by Flock is less general than rule-inheritance, but has proved sufficient for existing use-cases.</p>
<p>Secondly, Flock does not provide language constructs for controlling the order in which rules are scheduled (other than the ordering of the rules in the program file). ATL, for example, includes constructs that allow users to specify that rules are scheduled explicitly (lazy rules) or in a memoised manner (unique rules). We anticipate that scheduling constructs might be necessary for larger migration strategies, but have not yet encountered situations in which they have been required.</p>
<p>Thirdly, Flock is tailored for applying migration to a single original and a single migrated model. Although further models can be accessed by a Flock migration strategy, they cannot be used as the source or target of the conservative copy algorithm. By contrast, some general-purpose model transformation languages can access and manipulate any number of models.</p>
<p>Finally, Flock has been tailored to the model migration problem. In other words, we believe that Flock is well-suited to specifying model transformations between two metamodels that are very similar. For metamodel evolution in which the original metamodel undergoes significant and large-scale revision, a general-purpose transformation might be more suitable than Flock for specifying model migration.</p>
<h3 id="scope">Scope<a class="headerlink" href="#scope" title="Permanent link">&para;</a></h3>
<p>Flock is typically used as a manual specification approach in which model migration strategies are written by hand. As such, we believe that Flock provides a flexible and concise way to specify migration, and is a foundation for further tools that seek to automate the metamodel evolution and model migration processes. There are approaches to model migration that encompass both the metamodel evolution and model migration processes, seeking to automatically derive model migration strategies (e.g., <a href="http://www.eclipse.org/edapt/">Edapt</a>. These approaches provide more automation but at the cost of flexibility: for example, you might be restricted to using a tool-specific editor to perform model migration, or to using only EMF.</p>
<p>A more thorough discussion of the design decisions and execution
semantics of Flock can be found in a <a href="https://dl.acm.org/doi/10.1007/s10270-012-0296-2">SoSyM journal article</a>. Flock has been compared with other model migration tools
and languages in a <a href="https://link.springer.com/chapter/10.1007/978-3-642-16145-2_5">MoDELS paper</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="../epl/" title="Pattern matching (EPL)" 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>
Pattern matching (EPL)
</span>
</div>
</a>
<a href="../emg/" title="Model generation (EMG)" 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 generation (EMG)
</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>
<script src="../../assets/javascripts/vendor.d710d30a.min.js"></script>
<script src="../../assets/javascripts/bundle.b39636ac.min.js"></script><script id="__lang" type="application/json">{"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents"}</script>
<script>
app = initialize({
base: "../..",
features: [],
search: Object.assign({
worker: "../../assets/javascripts/worker/search.a68abb33.min.js"
}, typeof search !== "undefined" && search)
})
</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/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>
</body>
</html>