Heute möchte ich meine vorgehensweise zur SUM->View Transformation anhand von Pseudocode erläutern. Die Java-Implementierung ist etwas komplexer, doch im Kern spiegelt der Pseudocode meine programmatische Umsetzung wieder. Noch ein paar Hintergrundinformationen, bevor es zur Sache geht: Im Prinzip geht es darum, ein KobrA2-Modell (SUM), für das ich ein auf MDT UML basiertes Metamodell erstellt habe, in ein UML-Modell (View) zu transformieren. Dabei sollen speziell für die sogenannte SpecificationStructuralServiceView der KobrA2-Methode nur die «subject»-Komponente mit ihren public Attributen und Methoden, alle «acquired» Komponenten samt public Attributen und Methoden, sowie alle Generalisierungen (rekursiv) der Komponenten mit public Attributen und Methoden aus dem SUM extrahiert werden. Bis jetzt gehe ich davon aus, dass ich zusätzlich noch die verwendeten “Types” transformieren muss, obwohl in der KobrA2-Methode eine eigene View für die verwendeten Types vorgesehen ist. Doch während ich eben darüber nachgedacht habe, kann es sein, dass es ausreicht auf die Elemente im SUM zu referenzieren, falls sie nicht für die Transformation vorgesehen sind. Ob und inwieweit dies möglich ist, muss ich allerdings noch untersuchen. Nun zum Eingemachten 🙂

SUM->View Pseudocode

Der Hauptteil ist eigentlich ganz simpel. Und auch die folgenden ausgelagerten Funktionen sollten eigentlich selbsterklärend sein … k2s = select subject in SUM s = addComponentClass(k2s) apply stereotype «subject» to s . k2aCCs = select acquired componentClasses in SUM for each k2cc in k2aCCs: cc = addComponentClass(k2cc) a = add association between s and cc apply stereotype «acquired» to a . //TODO: add comments or better add constraints? or add both? //but don't know yet how -.- function addComponentClass(k2cc): if not k2cc already passed transformation: c = create class in view apply stereotype «componentClass» to c addPublicAttributes(k2cc, c) addPublicOperations(k2cc, c) addGeneralizations(k2cc, c) return c else: return class of view that represents k2cc function addPublicAttributes(k2classifier, classifier): for each k2property in (get owned attributes of k2classifier): if visibility of k2property is public: k2type = type of k2property translatedType = mapType(k2type) add attribute of translatedType with same name as k2property to classifier function addPublicOperations(k2class, class): for each k2operation in (get owned operations of k2class): if visibility of k2class is public: op = create operation in class with same name as k2operation for each k2param in (get owned parameters of k2operation): k2type = type of k2param translatedType = mapTyppe(k2type) param = add parameter of translatedType with same name as k2param to op set direction of param (same as k2param) set multiplicities of param if values != 1 (same as k2param) add op to class function addGeneralizations(k2classifier, classifier): for each k2general in (get general classifiers of k2classifier): if k2classifier is instance of K2ComponentClass: general = addComponentClass(k2general) if k2classifier is instance of Class: //this includes the case that k2classifier is a K2Class general = addClass(k2general) if k2classifier is instance of Interface: general = addInterface(k2general) else: ???? //what about PrimitiveType and Enumeration??? general = null . add generalization to classifier that points to general function addClass(k2class): if k2class has an according element in the view: if attributes and operations are missing: c = select Class from view else c = create Class in view . if c is not null: addPublicAttributes(k2class, c) addPublicOperations(k2class, c) addGeneralizations(k2class, c) . return c function addInterface(k2interface): if k2interface has an according element in the view: if attributes and operations are missing: i = select Interface from view else i = create Interface in view . if i is not null: addPublicAttributes(k2interface, i) addPublicOperations(k2interface, i) addGeneralizations(k2interface, i) . return i function mapType(k2type): if k2type has an according element in the view: viewType = according element else: if k2type is instance of K2ComponentClass //is this component automatically acquired??? viewType = addComponentClass(k2type) else //classifiers are added without any operations and attributes viewType = create Type of same MetaClass as k2type in view . return viewType