Jede Regel wird zu einer oder mehrerer Rollen in einer oder mehreren Compartments und bekommt noch einen Präfix Delete* Create* Synchronize*
Damit haben alle Regeln auf jeden Fall schonmal einen einmaligen namen
Andere Regeln wie Helper Regeln bekommen einen anderen Präfix und können als eigenes Compartment mit eigenen Rollen betrachtet werden
Beim Erstellungsregeln werden über das Synchronisationscompartment Verlinkung zwischen den Teilprojekten erzeugt, d.h. sobald es eine Regel gibt die Gleichheit zwischen Objekten spezifiziert oder das erstellen Managed, werden automatischen die Verlinkungen auf Instanzebene mit erstellt. Diese müssen dannach nicht nochmal neu in Regeln spezifiziert werden
Sobald sich die Synchronisationsregeln oder anderen Regeln ändern können diese zur Laufzeit ausgetauscht werden
Falls die Namen identisch bleiben müssen nur die Regeln neu geladen werden und ersetzen sich gegenseitig
Synchronization wird dann wieder auf den Punkt hergestellt und neue Modelle falls sie dazugekommen sind gleich mit integriert
Möchte ich den Fall abbilden können, dass ich ein Element in einem Modelverbund löschen aber nicht die Verknüpften Elemente mitlösche (Nein: da dies zu unkontrollierten Problemen führt => maximal woanders als gelöscht markieren)
darauf ergibt sich die Frage ob ich feingranulare Regeln überhaupt haben möchte oder ob mich eigentlich nur der Ansatz mit einer Regel die alles abbildet interessiert
Running Example for this Webpage
3 Modelle Families, Persons und SimplePersons
Konzept einer Person ist in jedem Modell verhanden
Änderungen von einem Model müssen an die anderen propagiert werden
Families (Model A)
class Family { lastName: String father: Member mother: Member sons: List[Member] daughters: List[Member]}class Member { firstName: String address: String birthday: Date familyFather: Member familyMother: Member familySon: Member familyDaughter: Member}
Persons (Model B)
class Person { fullName: String birthday: Date}class Male extends Person {}class Female extends Person {}
SimplePersons (Model C)
class SimplePerson { completeName: String address: String male: Boolean}
Objinv (Person, SimplePerson, Family o Member)with (Member.firstName + " " + Family.lastName, Person.fullName, SimplePerson.completeName)
Problem ist die Unterscheidung von männlich und weiblich, die kann ich hier nicht Abbilden, was natürlich die Problematik mit jeglicher Vererbung wieder mit sich bringt
Attribute invariant
Attinv (Person, SimplePerson, Family o Member)with (Member.firstName + " " + Family.lastName, Person.fullName, SimplePerson.completeName)
Als Synchronisationsregel möglich jedoch zum Erzeugen nicht ausreichend
Idee am Ende nur eine Regel Art aus der Synchronisations-, Lösch- und Erstellungsregeln erzeugt werden
COMPLETE RULES
Regeln, welche für Synchronization, Löschen und Erstellen verwendet werden können
Vorteil:
Kurze Regelschreibweise
Sobald Elemente in der Regel vergessen werden fällt dies schneller auf
Nachteil:
keine feingranuale Spezifikation der Regeln
Elementtypen werden für Löschen, Erstellen und Synchronisieren immer zusammenbetrachtet
Complete Rule
Code Generator muss Erstell-, Lösch- und Synchronisationsregeln aus einer so einer Regel generieren
Erzeugung von Objekten kann anhand von Sync Regeln abgeleitet werden
Trennung in primary Regeln und non-primary Regeln
primary Regeln bestimmen Objekte zwischen Modellen eindeutig
Alte Idee: Erzeugung von Objekten kann anhand der primary Regeln abgeleitet werden (Verkettung der primary Regeln für eindeutige Objekt erkennung zwischen Modellelementen verschiedener Modelle)
Probleme
Short Hand notationen für spezial Fälle die immer verwendet werden? Brauchen wir das wirklich?
Grenzen von change Operatoren definieren in folgenden Beispielen schon mit betrachtet
"primary" syncRule AddressesOfMemberAndSimplePerson {sync a : Families!Member c : SimplePersons!SimplePersonwith a.address == c.address}
Rule C
"primary" syncRule BirthdaysOfMemberAndPerson {sync a : Families!Member b : Persons!Personwith a.birthday == b.birthday}
Fälle Primary Rules
Wenn ich einen Modellverbund habe, wo alle Elemente auf die Regeln zutreffen in der Synchronisation enthalten sind, dann muss ich beim Insert nicht nach schon vorhandenen Elementen suchen, das würde nur bedeuten, dass das Element in dem Model wo es erstellt wurde schon existiert
Deswegen macht die unterscheidung in primary und non-primary Regeln keine Sinn
Außer man nutzt Primary Regeln für die integration von neuen Modellen
ALT Anfang
Fall (i): A (non-primary), B (non-primary), C (non-primary)
Keine Erzeugung von Objekten in anderen Modellen, möglich da keine Primary Regeln
Fall (ii): A (primary), B (non-primary), C (non-primary)
firstName + ' ' + lastName == fullName == completeName (bestimmen die Abhängigkeiten zwischen den Modellen eindeutig)
Namen als eindeutige Identifikation zwischen den Modellen angesehen
Fall (iii): A (primary), B (primary), C (primary)
firstName + ' ' + lastName == fullName == completeName && (address || birthday) (bestimmen die Abhängigkeiten zwischen den Modellen eindeutig)
Namen in Kombination mit Geburtstag oder Adresse bestimmen die eindeutigen Referenzen zwischen den Modellen
typisches muster von a.p + 'sep' + a.q ist schwer zu überführen
Möglich a.p+'sep'+a.q <a.changePandQ(syncValue)>
Oder im Allgemeinen nicht einfach übersetzen, wie z.B.: a.p1+':'+a.p2+'.'+a.p3*a.p4
Integrate the FeMaleSync
Female/Male Änderungen in den Modellen:
im Model Families Verweis umsetzen wenn es von männlich zu weiblich wird
im Model SimplePersons nur Attribute male neu setzen
im Model Persons dann eine delete und Insert methode und dann nur case schreiben
Problem:
Was mache ich beim Löschen mit Werten die vorher nie angefasst wurden?
Beispiel: Ändern einer Person im Persons Model von Male zu Female
Benötigen einer Kopie die den Zustand nach dem Löschen und neu erstellen wieder herstellt
Zwischen Werte irgendwie Abspeichern, jedoch sind einige Werte von der Person in keiner Regel definieren
Lösung: Person zwischen speichern und dann, neue Person mit alten Daten befüllen
syncRule FeMaleSync {sync a : Families!Member b : Persons!Person c : SimplePersons!SimplePerson d : Families!Family (a.family==d)with //Idee 1: instance of a.isFemale() == not c.male == b.isInstanceOf[Persons!Female] //Idee 2: case statement [syncValue as universal useable variable] a.isFemale() == not c.male == case(b, {syncValue==true: Persons!Female, syncValue==false: Persons!Male}) //Idee 3: everything case statement case(a, {syncValue==a.isFemale()}) == case(c, {syncValue==not c.male}) == case(b, {syncValue==true: Persons!Female, syncValue==false: Persons!Male})do a.switchGender(syncValue) //helper Function b.switchMaleFemale(syncValue) //helper Function c.male <- syncValue or c.switchMale(syncValue) //helper Function}Other Ideas OLD: a.isFemale<a.switchGender(syncValue)> not c.male<syncValue> b.isInstanceOf[Female]<b.switchMaleFemale(syncValue)> or case(b, {syncValue==true: Persons!Female, syncValue==false: Persons!Male})<b.switchMaleFemale(syncValue)> a.f(x) <a.g(y,x)> == y c.male <- not a.isFemale() == b instanceOf Female t1 : Persons!Female <- a.isFemale() == not c.male t2 : Persons!Male <- not a.isFemale() == c.male a.changeIsFemale(<- c.male == b instanceOf Male)
Anmerkungen:
instanceof ist zwar Boolean aber not (instance of Female) ist nicht sinnvoll.
Beispiel Operator: case(b, {true: Persons!Female, false: Persons!Male})
General Operator: case(o, {v_1:Model!Element1, ... v_n:Model!ElementN}) where Model is an arbitrary model and Element1 till ElementN elements in this model. Moreover, v_1 till v_n are arbitrary primitive (later object) values.
Noch generellere wäre v_1 könnte c.age>4 \land c.age<10 sein, damit könnte ich Phasen oder Altersgruppen in Modell Instanzen synchronisieren
Hilfs Funktion (Families) Mother<-> Father & Daughter <-> Son
Anders wäre die Transformation von Persons und SimplePersons zu Families nicht möglich
Funktion setzt Mütter zu Väter, Tochter zu Sohn und umgekehrt
Methode müsste aufgerufen werden falls so eine Änderung in Persons oder SimplePersons auftritt
Problem:
da diese Änderungen auch in die Family Klasse übernommen werden müssen kann es sein das dort eine Vater Relation überschrieben wird oder eine Mutter Relation überschrieben wird, da es sich um opposite Relationen handeln kann
Dies würde zu einer nicht mehr handhabbaren Veränderung führen
helper context Families!Member def : switchGender (female : Boolean) : Unit =if female then //female case (set to female) if self.familyFather.oclIsUndefined () then if not self.familySon.oclIsUndefined () then self.familyDaughter <- self.familySon endif else self.familyMother <- self.familyFather endifelse //not female case if self.familyMother.oclIsUndefined () then if not self.familyDughter.oclIsUndefined () then self.familySon <- self.familyDughter endif else self.familyFather <- self.familyMother endifendif;
Hilfs Funktion (Persons) Male <-> Female
Müsste wie ein Delete und Insert interagieren self.type <- Person!Female
Befehl vielleicht noch ändern nur wie? TODO
helper context Persons!Person def : switchMaleFemale (female : Boolean) : Unit =if female then //female case (set to female) if self.isInstanceOf[Persons!Male] then self.type <- Person!Female endifelse //not female case (set to male) if self.isInstanceOf[Persons!Female] then self.type <- Person!Male endifendif;
Hilfs Funktion (SimplePersons) male attribute
Braucht nicht extra eine Hilfsfunktion muss nur Attribute umsetzen
Befehl vielleicht noch ändern nur wie? TODO
helper context SimplePersons!Person def : switchMale (female : Boolean) : Unit =if female <> self.male then //change if different self.male <- femaleendif;
Integration of PhoneBook Model: extension of syncrules
primary Operator, um zu sehen welche Regeln nötig sind um ein Model in die existierende Synchronisation einzubeziehen
hier wäre nur Model B notwendig, da es das einzige interagierende in der primary Regel ist
Erweiterungsregel könnte als neues Compartment einfach mit eingeladen werden
Möglich Regel zu neuer großer Regel zu kombinieren und dann mit einmal neu einzuladen (jedoch dann nicht mehr ganz klar, welches Model neu ist, und wie dies gleich in die existierende Synchronisation integriert wird)
Delete Phone Book Model from Synchronization
delete PhoneBook könnte genutzt werden um ein Model komplett aus der Synchronisation zu löschen
Regeln würden weiter exisiteren jedoch würde er intern alles davon betroffene ignorieren
SPLIT INTO 3 RULE TYPES
Synchronizations-, Lösch und Erstellungsregeln einzeln definieren und dann in dazugehörigen Compartments umsetzen
Vorteil:
Feingranulare Spezifikation der Regeln in der Synchronisationssprache
Element typen können speziell aus dem Löschprozess rausgehalten werden
Nachteil:
Mehr schreib Aufwand für Regel Spezifikation
Sobald Regeln vergessen werden können diese nicht umgesetzt werden
Synchronization Rules
3 Ideen wie Synchronisationsregeln aussehen könnten die 3. ist dabei die vermutlich Eleganteste
die 2. ist nur abgewandelt zur 1. und eigentlich sinnlos
Idee 1
Jede Regel sagt genau welche anderen Objekte sie verändert und sorgt dafür das nicht das gleich Model nochmal angefasst wird
1 zu n
syncRule syncFirstNameFromMember {from a : Families!Member (firstName) //variablen Änderung auf die diese Regel reagieren sollin b : Persons!Person ( b.fullName <- a.firstName + ' ' + b.lastName //idee in part darf nur von from part beeinflusst werden und nicht von anderem in part ), c : SimplePersons!SimplePerson ( c.completeName <- a.firstName + ' ' + c.lastName //darf nicht von b beeinflusst werden )}syncRule syncLastNameFromFamily {from a : Families!Family (lastName) //variablen Änderung auf die diese Regel reagieren sollin b : Persons!Person ( b.fullName <- b.firstName + ' ' + a.lastName ), c : SimplePersons!SimplePerson ( c.completeName <- c.firstName + ' ' + a.lastName )}syncRule syncFullNameFromPerson {from b : Persons!Person (fullName)in a : Families!Member ( a.firstName <- b.firstName ), d : Families!Family ( d.lastName <- b.lastName ), c : SimplePersons!SimplePerson ( c.completeName <- b.fullName )}syncRule syncCompleteNameFromSimplePerson {from c : SimplePersons!SimplePerson (completeName)in a : Families!Member ( a.firstName <- c.firstName ), d : Families!Family ( d.lastName <- c.lastName ), b : Persons!Person ( b.fullName <- c.completeName )}
Idee 2
Nachteil Änderungen werden auch im eigenen Model nochmal durchgeführt, da die Funktion syncNames nicht unterscheidet von welchem Element sie aufgerufen wird
diese Regeln Rufen immer nur die Synchonisationsfunktion auf und bestimmen selbst nur welches Änderung als Event fungiert
1 zu n mit event trigger
syncRule syncCompleteNameFromSimplePerson {from c : SimplePersons!SimplePerson (completeName)do syncNameFunction (c.firstName : String, c.lastName : String) // wieder mit Nutzung der Hilfsfunktionen}syncRule syncFirstNameFromMember {from a : Families!Member (firstName) //variablen Änderung auf die diese Regel reagieren solldo syncNameFunction (a.firstName : String, a.lastName : String) // wieder mit Nutzung der Hilfsfunktionen}syncRule syncLastNameFromFamily {from a : Families!Family (lastName) //variablen Änderung auf die diese Regel reagieren solldo syncNameFunction (a.firstName : String, a.lastName : String) // wieder mit Nutzung der Hilfsfunktionen}syncRule syncFullNameFromPerson {from b : Persons!Person (fullName)do syncNameFunction (b.firstName : String, b.lastName : String) // wieder mit Nutzung der Hilfsfunktionen}
diese Regel kümmert sich um die Durchführung der Synchronisation und wird nur von denen davor aufgerufen wenn eine Änderung wo eintritt
deleteRule MembersAndPersonsAndSimplePersons { of s1 : Families!Member s2 : SimplePersons!SimplePerson s3 : Persons!Person without (Ich weiß nicht ob man das benötigt) s3 : Persons!Person}
Regel für interne Relationen in Modellen
Eigentlich uninteressant für die Sprache jedoch wäre es schon schön die irgendwie mit abzudecken
Verwenden von kompletten Regeln (1) und getrennten Regeln (2)
Vorteil:
kurze Regelschreibweisen möglich
feingranuales betrachten von Elementtypen möglich
Nachteil:
kompliziertere Regelsprache durch das Abdecken aller Fälle
kann zu unübersichtlichkeiten innerhalb der Regeln kommen
oberen 2 Ansätze verbinden
erst möglich falls beide Ansätze komplett ausgearbeitet sind
HELPER CONTEXT RULES (from ATL)
Können wir in unserem Ansatz einfach wieder verwenden
Neues Compartment für Helper Regeln mit einer Menge an Rollen für verschiedene Elemente aus den unterschiedlichen Modellen
Beispiele eine Rolle für Families!Member welche die Funktionen implementiert:
helperFamily : Families!Family
helperFamilyName : String
helperIsFemale : Boolean
helper context Families!Member def : family : Families!Family = if not self.familyFather.oclIsUndefined () then self.familyFather else if not self.familyMother.oclIsUndefined () then self.familyMother else if not self.familySon.oclIsUndefined () then self.familySon else self.familyDaughter endif endif endif;helper context Families!Member def : familyName : String = if not self.familyFather.oclIsUndefined () then self.familyFather.lastName else if not self.familyMother.oclIsUndefined () then self.familyMother.lastName else if not self.familySon.oclIsUndefined () then self.familySon.lastName else self.familyDaughter.lastName endif endif endif;helper context Families!Member def : isFemale () : Boolean = if not self.familyMother.oclIsUndefined () then true else if not self.familyDaughter.oclIsUndefined ( ) then true else false endif endif;
Helper Regeln um an die firstName und lastName Elemente aus Person und SimplePerson zu kommen