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