I have been trying to figure out whether the TextUML notation for action semantics can be dealt with properly by tools such as Xtext and EMFText (class models and state machines should be fine). For example, given this structural model fragment:
class Advertisement
attribute summary : String;
attribute description : String;
attribute keywords : Keyword[*];
attribute category : Category;
operation addKeyword(keywordName : String);
static operation findByCategoryName(catName : String) : Advertisement[*];
end;
association AdvertisementKeyword
role Advertisement.keywords;
role advertisement : Advertisement;
end;
class Keyword specializes Object
attribute name : String;
end;
class Category specializes Object
attribute name : String;
attribute description : String;
end;
association AdvertisementCategory
role Advertisement.category;
role ad : Advertisement[*];
end;
Notice the Advertisement class declares two operations. Their behaviour in TextUML could be written as:
operation Advertisement.addKeyword;
begin
var newKeyword : Keyword;
newKeyword := new Keyword;
newKeyword.name := keywordName;
link AdvertisementKeyword(keywords := newKeyword, advertisement := self);
end;
operation Advertisement.findByCategoryName;
begin
return Advertisement extent.select(
(a : Advertisement) : Boolean {
return a->AdvertisementCategory->category.name = catName;
}
);
end;
Note that TextUML allows the behavior to be specified inline when declaring an operation in a class, or in separate, as above (that explains the lack of parameters, modifiers etc).
In the resulting UML model, the behaviour of Advertisement.addKeyword would roughly map to this (using a textual pseudo-notation for UML activities that is hopefully more readable than raw XMI):
activity(name: "addKeyword") {
structuredActivityNode {
variable(name: "newKeyword", type: #String)
writeVariable(variable: #newKeyword, value: createObject(class: #Keyword))
writeAttribute(
attribute: #Keyword.name,
target: readVariable(variable: #newKeyword),
value: readVariable(variable: #keywordName)
)
createLink(
association: #AdvertisementKeyword,
end1: #AdvertisementKeyword.keyword,
end1Value: readVariable(variable: #newKeyword),
end2: #AdvertisementKeyword.advertisement,
end2Value: readSelf()
)
}
}
and the behaviour Advertisement.findByCategoryName would map to this:
activity(name: "findByCategoryName") {
structuredActivityNode {
// implicit variable for return value
variable(name: "@result", type: #Advertisement, upperBound: *)
// implicit variable for parameter value
variable(name: "catName", type: #String)
writeVariable(
variable: #@result,
value: callOperation(
operation: #Advertisement.select,
target: readExtent(class: #Advertisement),
filter: metaValue(#@findByCategoryName_closure1)
)
)
}
}
// a closure is an activity that has a reference to a context activity
closure(name: "@findByCategoryName_closure1") {
// implicit variable for return value
variable(name: "@result", type: #Boolean)
// implicit variable for parameter value
variable(name: "a", type: #Advertisement)
writeVariable(
variable: #@result,
value: callOperation(
operation: #Object.equals,
// variables from the context activity are available here
target: readVariable(variable: #catName)
args: readAttribute(attribute: #Category.name, target: readLink(
association: #AdvertisementCategory,
fedEnd: #Advertisement.ad,
fedEndValue: readVariable(variable: #a),
readEnd: #Advertisement.category
))
)
)
}
Note that UML does not have closures, this is an extension to the UML metamodel which I wrote about here before.
Some background on the metaclasses involved: ReadVariableAction, CreateObjectAction, CreateLinkAction, ReadExtentAction etc are all action metaclasses. Actions are the building blocks for modeling activity behaviour in UML.
The million dollar question is: can Xtext and EMFText handle more complex textual notations like this? Is this out of the happy path? Has anyone done something similar? I am under the impression I could use Xtext or EMFText better if I used them based on a intermediate metamodel for behavior that would be closer to the concrete syntax (to get all the IDE bells and whistles for free) and then transformed that to UML in a separate step.
If you have the answers for any of these questions (or even if you have comments and questions of your own), please chime in.