Sunteți pe pagina 1din 6

Navigarea modelului

Oricarui element din metamodel (DslDefinition.dsl) de fapt corespunde o clasa cu proprietati, care
corespund proprietatilor si relatiilor definite in metamodel. Aceasta clasa este derivata dintr-o
anumita clasa (in dependenta de tipul elementului) predefinita si mosteneste un set de metode,
care permit accesarea, modificarea elementelor si proprietatilor lor, si navigarea in model.

Fiecare element din metamodel este legat cu notatia lui. Acestei notatiei tot corespunde o clasa
derivata dintr-o anumita clasa de prezentare (vezi fig.1 . roz – elemente model, albastru -
reprezentari)

Fig.1 Clase de baza pentru elementele metamodelului

Modelul particular creat in baza metamodelului reprezinta de fapt Instantele (obiectele) claselor
definite in metamodel :

PageElement aPage = ... ;// clasa derivata din clasa ModelElement

Instantele claselor definite in DslDefinition.dsl sunt pastrate intr-o structura de date speciala numita
In-Memory Store (IMS) sau Store. Orice clasa definita in DSL preia Store ca argument al
constructorului. De exemplu:

PageElement page = new PageElement (theStore);

Proprietati
Proprietatile claselor definite in metamodelul DSL, devin proprietatile claselor in codul de program
corespunzator:

PageElement aPage = ... ;


if (aPage.isRoot == True) ... ;
if (aPage.Address.EndsWith(".html")) ... ;
Daca intre doua clase este definite o relatie, atunci instantele ambelor clase au proprietati, care
permit navigarea catre capatul opus al legaturii. Denumirile proprietatilor apar in metamodel ca
etichetele rolurilor asupra ambelor capetelor relatiei. In dependenta de multiplicitatea rolului, tipul
proprietatii corespunzatoare va fi o clasa sau o colectie de clase. De exemplu, daca avem o relatie
numita ParintiAuCopii intre doua Persoane, capetele relatiei avand roluri multiple Parinti si,
respectiv, Copii, atunci poate fi scris codul urmator:

Ion.Copii.Add(Maria);
// adaugarea relatiei intre obiect Ion si Maria, unde Maria este copil

Acum ambele expresii sunt adevarate:

Ion.Copii.Contains(Maria);
Maria.Parinti.Contains(Ion);

Acelasi effect ar putea fi atins prin scrierea:

Maria.Parinti.Add(Ion);

Accesarea fiecarului element din colectie:

foreach (Persoana copil in Ion.Copii) { ... }

Relatii
O relatie din metamodelul DSL poate avea instante intr-un model particular. Instantele relatiei se
numesc legaturi. O legatura intotdeauna are un element-sursa si un element-destinatie. Tipul lor
poate fi acelasi. Obiectul legaturii si proprietatile lui (sursa si destinatie) pot fi accesate in felul
urmator:

ParintiAuCopii legatura = ParintiAuCopii.GetLink(Ion, Maria);

if (legatura.Parent == Ion) {...}

if (legatura.Child == Maria) {...}

Daca in metamodel se permit legaturi multiple intre elemente, atunci aceste legaturi sun accesate cu
ajutorul GetLinks:

foreach (ParintiAuCopii legatura in ParintiAuCopii.GetLinks(Ion, Maria)) {...}

sau

foreach (ParintiAuCopii legatura in ParintiAuCopii.GetLinksToChildren(Ion)) {...}

In metamodelul (definitia DSL) la unele roluri particulare proprietatea Is Property Generated pot
avea valoarea false. Atunci pentru acest rol nu este generata proprietatea. Totusi si in acest caz
legaturile pot fi accesate si traversate, utilizand metodele clasei-relatie:

foreach (Persoana p in ParintiAuCopii.GetChildren(Ion)) { ... }


Un exemplu de relatie cu rolurile “ascunse” este relatia PresentationViewsSubject, care leaga
elementul modelului cu figura, care il reprezinta pe diagram

PresentationViewsSubject.GetPresentation(aPage)[0] as PageShape

Directoriu de elemente

Toate elementele din deposit Store pot fi accesate utilizand directoriu de elemente:

store.ElementDirectory.AllElements

Metode pentru gasirea elementelor:

store.ElementDirectory.FindElements(Persoana.DomainClassId);
store.ElementDirectory.GetElement(elementId);

Accesarea Informatiilor despre clase, relatii si alte aspecte ale metamodelului


Exemple:

DomainClassInfo pageClass = aPage.GetDomainClass();


DomainPropertyInfo addressProperty =
pageClass.FindDomainProperty("Address")
DomainRelationshipInfo relationship =
link.GetDomainRelationship();
DomainRoleInfo sourceRole = relationship.DomainRole[0];

Modificarea modelului
Oriche schimbare in model (in elemente, relatii, figuri, diagrame etc. ) trebuie facuta in asa numita
tranzactie. De exemplu:

using (Transaction t = store.TransactionManager.BeginTransaction("updates"))


{
// schimbari in depozit
t.Commit();
}

Daca o exceptie are loc in timpul schimbarilor, astfel incat metoda Commit() nu este indeplinita,
atunci depozitul Store va fi resetat in starea sa initiala. Astfel modelul niciodata nu va fi inconsistent.

Cea mai buna metoda este utilizarea instructiunii try … catch:

Store store; ...


SiteModel site = ...// element-radacina a modelului
try
{
using (Transaction transaction =
store.TransactionManager.BeginTransaction("update model"))
// tranzactia trebuie sa aiba denumirea.
{
// Schimbari in depozitul Store:
Page p = new Page(store);
p.SiteModel = site; //
p.Name = "About";
p.Address = "about.html";
// sfarsitul schimbarilor

transaction.Commit(); // Important!

} // tranzactia s-a incheiat


}
catch (Exception ex)
{
// Daca apare o exceptie, depozitul va fi restabilit
// in starea precedenta.
}

In cadrul tranzactiei poate fi facut orice numar de schimbari. Tranzactii noi pot fi deschise in cadrul
unei tranzactiei active. Apelul la metoda Commit la incheierea tranzactiei face toate schimbarile
permanente. In cazul unei exceptiei depozitul restabileste starea precedenta.

Accesarea modelelor din sabloane T4

Notiuni de baza despre sabloane


Utilizand sabloane T4 poate fi generat orice fisier text (rapoarte, codul sursa, fisiere de configurare,
XML, HTML, etc).

Sabloane textuale sunt prelucrare in regimul experimental, cand depanati DSL, sau acolo unde veti
amplasa limbajul.

Sabloanele se pastreaza in fisiere textuale cu extensia .tt si contin urmatoarele tipuri de constructii :

 Directivele – elemente care controleaza modul de procesare a sablonului.


 Blocuri text  - continut copiat direct, fara schimbari in fisierul rezultant.
 Blocuri de control – cod de program care insereaza valorile variabilelor in text, si controleaza
generarea conditionata sau repetata a textului.

Directivele sunt instructii generatorului despre cum, in baza carui model si unde va fi generat codul.
Exemplu de directiva (observati formatarea/marcajul) :

<#@ output extension=".txt" #>


Textul nu are nici o formatare speciala si se copie fara nici o schimbare, pastrand pozitia initiala. In
exemplu urmator va fi generat fisier txt care contine cuvantul  « Hello » :

<#@ output extension=".txt" #>


Hello
Blocuri de control contin instructiunile utilizate pentru generarea. Implicit limbajul instructiunilor
este C#, dar poate fi utilizat si limbajul Visual Basic (VB). Orice bloc de contrul este delimitat de
simbolurile <# ... #>

In exemplu urmator in fisierul rezultant va fi scris cuvantul  « Hello » :

<# Write(‘Hello’) #>

In sabloane t4 blocuri de control nu pot contine alte blocuri de control, dar pot fi mixate cu blocuri
de text :

<#
for(int i = 0; i < 4; i++)
{
#>
Hello!
<#
}
#>

Exista o variatie a blocurilor de control, utilizata pentru calcularea expresiilor si inserarea valorii in
text. Blocuri de control de tip expresie se delimiteaza prin simbolurile <#= ... #>

Exemplu:

<#@ output extension=".txt" #>


<#
for(int i = 0; i < 4; i++)
{
#>
This is hello number <#= i+1 #>: Hello!
<#
}
#>

Accesarea modelului din sablon


Pentru a accesa modelul dintr-un sablon trebuie:

De adaugat in directiva template proprietatea


inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" pentru a
avea acces la depozitul modelului Store

De specificat procesorul de directive, care va permite accesarea tuturor claselor, relatiilor etc din
model si va incarca modelul din fisierul specificat

Exemplu:
<#@ template
inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransfor
mation" #>
<#@ output extension=".txt" #>
<#@ MyLanguage processor="MyLanguageDirectiveProcessor"
requires="fileName='Sample.myDsl1'" #>

Sablonul acum permite urmatoarele:

 Utilizarea claselor domeniului, proprietatilor, relatiilor definite in metamodel.


 Modelul necesar se incarca utilizand proprietatea requires.
 Obiectul this are o proprietate, care contine elemental-radacina al modelului. Incepand de la
acest obiect puteti naviga orice alt element al modelului. Numele proprietatii coincide cu
denumirea clasei-radacina. De exemplu: this.SiteModel.

Un sablon poate accesa mai multe modele:

<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor"


requires="fileName='Library.xyz'" provides="ExampleModel=LibraryModel" #>
<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor"
requires="fileName='School.xyz'" provides="ExampleModel=SchoolModel" #>

S-ar putea să vă placă și