blob: 23e03651723f2c05c9671670b21b27199f7595eb [file] [log] [blame]
-*
This transformation runs very slowly for the large model, which contains
a much larger number of IdentifierReferences (198141) than Classes (4586).
In particular, only 11 of the 4586 classes are to be transformated to states,
and hence many of the identifier references are contained in classes that
are not states, and do not need to be transformed.
Using the @lazy annotation on the IdentifierReference2Transition does
not seem to improve performance, possibly because DefaultTransformationStrategy
is used instead of FastTransformationStrategy when an ETL transformation
has any rules that use the @lazy annotation.
*-
pre {
var machine = new StateMachine!StateMachine;
Class.all.size.println("Classes: ");
IdentifierReference.all.size.println("IdentifierReferences: ");
}
rule Class2State
transform c : Java!Class
to s : StateMachine!State {
guard: c.isState()
s.name = c.name;
machine.states.add(s);
s.out = c.members.select(m : Method | true).collect(m|m.eAllContents.select(e:IdentifierReference|true)).flatten().equivalent();
}
rule IdentifierReference2Transition
transform ir : Java!IdentifierReference
to t : StateMachine!Transition {
guard: ir.isTransition()
t.src = ir.getClass().equivalent();
t.dst = ir.getTargetClass().equivalent();
t.trigger = ir.getTrigger();
t.action = ir.getAction();
machine.transitions.add(t);
}
@cached
operation IdentifierReference isTransition() : Boolean {
return self.getClass().isState() and
self.next.isDefined() and self.next.target.name == "Instance" and
self.next.next.isDefined() and self.next.next.target.name == "activate";
}
@cached
operation IdentifierReference getClass() : Class {
var class = self;
while (not class.isKindOf(Class)) {
class = class.eContainer();
}
return class;
}
@cached
operation IdentifierReference getTargetClass() : Class {
return Java!Class.all.selectOne(c|c.name == self.target.name);
}
@cached
operation IdentifierReference getTrigger() : String {
if (self.getContainingMethod().name <> "run") {
return self.getContainingMethod().name;
} else if (self.getContainingStatementListContainer().isKindOf(NormalSwitchCase)) {
return self.getContainingStatementListContainer().condition.target.name;
} else if (self.getContainingStatementListContainer().isKindOf(CatchBlock)) {
return self.getContainingStatementListContainer().parameter.typeReference.classifierReferences.first.target.name;
} else {
return "--";
}
}
@cached
operation IdentifierReference getContainingMethod() : String {
var method = self;
while (not method.isKindOf(Method)) {
method = method.eContainer();
}
return method;
}
@cached
operation IdentifierReference getAction() : String {
var send = self.getContainingStatementListContainer().getSendMethod();
if (send.isDefined()) {
return send.arguments.first.next.target.name;
} else {
return "--";
}
}
@cached
operation IdentifierReference getContainingStatementListContainer() : StatementListContainer {
return self.eContainer().eContainer();
}
@cached
operation StatementListContainer getSendMethod() : MethodCall {
var statementContainingSendMethod = self.statements.selectOne(s:ExpressionStatement|s.expression.isKindOf(MethodCall));
if (statementContainingSendMethod.isDefined()) {
return statementContainingSendMethod.expression;
}
}
@cached
operation Class isState() : Boolean {
return self.isConcrete() and self.anySuperTypesIsState();
}
@cached
operation Class isConcrete() : Boolean {
return not self.annotationsAndModifiers.exists(m|m.isKindOf(Abstract));
}
@cached
operation Class anySuperTypesIsState() : Boolean {
if (self.getSuperType().isDefined()) {
if (self.getSuperType().name == "State") {
return true;
} else {
return self.getSuperType().anySuperTypesIsState();
}
}
return false;
}
@cached
operation Class getSuperType() : Class {
var supertype : Class = null;
if (self.`extends`.isDefined() and self.`extends`.getClassifier() <> self) {
supertype = self.`extends`.getClassifier();
}
return supertype;
}
@cached
operation NamespaceClassifierReference getClassifier() {
return self.classifierReferences.first.getClassifier();
}
@cached
operation ClassifierReference getClassifier() {
var classifier = null;
// some classes aren't contained in this model, e.g. Throwable
if (self.target.isDefined() and Java.owns(self.target)) {
classifier = self.target;
}
return classifier;
}