Transzformáció¶
A transzformáció alrendszer egy beágyazott mini DSL nyelv a hozzá tartozó csomópontokkal és kódgeneráló funkciókkal. Általában validációs/adatgyűjtő, A->A és A->B transzformáció típus is valósítható meg. Az egyes elemekre kulcs, minta vagy foglalat (slot) találati szabályokat lehet létrehozni. Jelenleg csomópont fa struktúrához készült, speciális gráf felépítéshez egyedi szabályok vagy többmenetes transzformációk kellenek.
Találati stratégiák¶
alapértelmezett: minden önálló objektum tesztelődik, nem kötelező a találat, több találat esetén figyelmeztetés jön létre.
strict: minden önálló objektumra találatnak kell létrejönni, maximum egynek.
enforced: minden önálló objektumra és osztály tag tesztelődik, nem kötelező a találat.
Első szintű találat¶
Az első elem vagy egy tároló, vagy egy elemből álló «azonosító» csomópont, ami csak egyszer fordul elő. Ezért az első
szintre külön szabályok vonatkoznak. Ezeket [root]
attribútummal kell megjelölni.
Találati módok¶
Annak kiválasztása, hogy a soron következő csomópontra melyik találatot kell alkalmazni.
Kulcs¶
Csomópont típusra, útvonalra vagy névre készíthető találati feltétel. Váltózók használata nem lehetséges.
Példák:
<%Data::String%>
: a string típusra ad találatot.<%:xml::#Element tag="test"%>
: olyan :xml::#Element típusra ad találatot, ahol a «tag» váltózó „test” értékű.<%:xml::#Element tag="main"/:xml::#Element tag="child" %>
: olyan :xml::#Element típusra ad találatot, ahol a «tag» váltózó „main” értékű és az egyik tárolójában van olyan elem, ami :xml::#Element típusú és a «tag» változója „child” értékű. Itt a „van olyan útvonal, ahol..” elv érvényesül. A konkrét útvonalak megadása a*next{}
mezőben lehetséges .
Minta¶
Egyedi teszttel dönthető el a találat kifejezések segítségével. A feltételek között «bool» típusú metódus megadása is lehetséges.
*pattern XmlMain {
*match <%:xml::#Element%> {
$1.tag == "main";
$1.container.size() == 1;
}
}
Slot és SlotUse¶
Az első hívással váltózókat hozunk létre és állítunk be, a SlotUse a változók alapján dönti el a találat tényét. Előnye például a lokális változók transzformációjakor jelentkezik, amikor a feloldott (teljes) típust tesszük a változóba, és adjuk tovább. Így csomópontonként egyszer történik típuskeresés (Slot), a további tesztelés már csak sima összehasonlítás (SlotUse).
*slot LocalDeclare {
*provides {
type: Data::String;
name: Data::String;
}
*match declare: Code::VariableDeclare {
}
*fill {
type = transformHelper.findType(declare.variableType.@string);
name = declare.variableName;
}
}
*slotuse MyVariable: LocalDeclare {
*match {
type == "MyFullType";
}
*pre {
System::stdout("MyVariable...\n");
}
}
Kód végrehajtása a találaton¶
Két blokk adható meg, az egyik a gyerek csomópontok feldolgozása előtt, a másik utána.
*pre {
// Előtte fut le a $1 csomóponton.
}
*post {
// Utána fut le a $1 csomóponton.
}
Következő elemek kiválasztása¶
Külön szabály megadása nélkül a példányosított objektum összes gyerek csomópontja szerepelni fog a keresési listában. Lehetőség van üres keresési lista megadására.
*next {}
Vagy a tagokat felsorolva csak a megadott elemekből keresési listát készíteni.
*next {
container.@children;
}
Vagy a kódból is meghívható egy speciális metódus (@mainlist).
*pre {
*foreach (#UserType data: $1.list) {
@mainlist(data);
}
}
*next {}
A találati szabály nevének használatával közvetlen találatok használhatóak.
*pre {
Rule1($1.member1);
Rule2($1.member2);
}
*next {}
Visszatérési érték és típus megadása¶
Deklaráció nélkül egy státust taralmazó Data::Bool érték kerül visszaadásra. Egyedi típust az onResult() metódussal adhatunk meg.
*method UserType onResult () {
return UserType(value);
};
Implementáció¶
Végrehajtás előtt a transzformációs adatok és szabályok egy klasszikus osztályba szerveződnek (Group::Class). Minden tag váltózó, metódus és alap osztály közös lesz. Speciális módon osztályként és funkcióként is használható.
*entrypoint main () {
// Tetszőleges kezdő elem.
Node root = init();
// Funkció hívás egyszerű transzformációhoz.
UserType result1 = TestTransform (root);
// Osztály példányosítás.
TestTransform testTransform;
// Feldolgozási értékek megadása.
testTransform.member = "value";
// Feldolgozás indítása a beépített main() metódussal.
UserType result2 = testTransform.main (root);
};
Példa¶
//! Teszt transzformáció.
[std:strict]
*transform Test {
//! Közös tag változó.
Data::String member;
//! Közös metódus.
*method testMethod () {
};
//! Találati szabály csak az első elemre.
[std:root]
*key RootMatch: <%RootType%> {
*next {
container.@children;
}
}
//! Találati szabály a további elemre.
*key UserMatch <%UserType%> {
*pre {
// Előtte fut le a $1 csomóponton.
}
*post {
// Utána fut le a $1 csomóponton.
}
*next {
container.@children;
}
};
};