blob: 17ffb854d44fd8e5a75be4342ae6d01e10b432ec [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013, 2016 CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
* Christian W. Damus - bug 465656
*****************************************************************************/
import RSAToPapyrus;
modeltype notation "strict" uses 'http://www.eclipse.org/gmf/runtime/1.0.2/notation';
modeltype umlNotation "strict" uses 'http://www.eclipse.org/papyrus/umlnotation';
modeltype uml "strict" uses 'http://www.eclipse.org/uml2/5.0.0/UML';
modeltype ecore "strict" uses 'http://www.eclipse.org/emf/2002/Ecore';
modeltype sash "strict" uses 'http://www.eclipse.org/papyrus/0.7.0/sashdi';
modeltype config "strict" uses 'http:///RSAToPapyrusParameters.ecore';
transformation RSAStateMachineDiagram(inout semantics : uml, inout graphics : notation, out di : sash, in param : config);
main() {
semantics.rootObjects()[uml::Element]->map toOwnedDiagrams();
}
query View::getDiagramType() : String{
return 'PapyrusUMLStateMachineDiagram';
}
mapping notation::Diagram::generateDiagram() : notation::Diagram inherits Diagram::toPapyrusDiagram when {
self.type = 'Statechart'
}{
end {
graphics.objectsOfType(DecorationNode)->select(type = 'Region_SubvertexCompartment').map addInRegion();
graphics.objectsOfType(Shape)->select(type = 'StateMachine_Shape').map createIntermediateCompartment();
graphics.objectsOfType(Shape)->select(type = 'State_Shape').map createStructureCompartment();
graphics.objectsOfType(DecorationNode)->select(type = 'StateMachine_NameLabel').map addLayout();
graphics.objectsOfType(DecorationNode)->select(type = 'State_NameLabel').map fixLayout();
graphics.objectsOfType(Shape)->select(type='Comment_Shape').map addCommentDecoration();
graphics.objectsOfType(Shape)->select(type = 'Constraint_Shape').map addConstraintDecoration();
}
}
mapping inout Shape::createIntermediateCompartment() {
var compartment := object DecorationNode {
type := 'StateMachine_RegionCompartment';
layoutConstraint := object Bounds{}
};
compartment.children := self.children->select(type = 'Region_Shape');
children := children->insertAt(2, compartment); /* Required for layout: the Structure Compartment of the Region must be in 2nd position */
}
mapping inout DecorationNode::addInRegion() {
var currentParent := self.oclAsType(EObject).eContainer();
var currentBounds := self.layoutConstraint.oclAsType(Bounds);
var region := object Shape {
type := 'Region_Shape';
layoutConstraint := object Bounds{
x := currentBounds.x;
y := currentBounds.y;
};
element := self.element;
children := self;
eAnnotations := object EAnnotation {
source := "RegionAnnotationKey";
details := object EStringToStringMapEntry{
key := "RegionZoneKey";
value := 'B';
}
}
};
if self.layoutConstraint.oclIsUndefined() then self.layoutConstraint := object Bounds{} endif;
self.styles := self.styles->reject(oclIsTypeOf(TitleStyle));
currentParent.oclAsType(View).children += region;
}
mapping inout Shape::createStructureCompartment() when {
not self.children->exists(type = 'State_RegionCompartment')
}{
var compartment := object DecorationNode {
type := 'State_RegionCompartment';
visible := self.children->exists(type='Region_Shape');
layoutConstraint := object Bounds{};
};
compartment.children += children->select(type = 'Region_Shape');
children := children->insertAt(2, compartment);
}
mapping inout DecorationNode::addLayout() {
if self.layoutConstraint.oclIsUndefined() then self.layoutConstraint := object Bounds{} endif;
}
mapping inout DecorationNode::fixLayout(){
var bounds := if self.layoutConstraint.oclIsUndefined() then object Bounds{} else self.layoutConstraint.oclAsType(Bounds) endif;
self.layoutConstraint := bounds;
if bounds.height < 20 then bounds.height := 20 endif;
}
mapping Node::toNode() : Node disjuncts
UMLShape::toPapyrusShape,
UMLShapeCompartment::toStructureCompartment,
BasicSemanticCompartment::toListCompartment,
BasicDecorationNode::toConnectorLabel,
BasicDecorationNode::toLabel
//TODO: Disjunct nodes mapping
;
mapping Edge::toEdge() : Edge disjuncts
UMLConnector::toCommentLink,
UMLConnector::toConstraintLink,
UMLConnector::toPapyrusConnector
//TODO: Disjunct edges mapping
;
mapping UMLShapeCompartment::toStructureCompartment() : DecorationNode inherits UMLShapeCompartment::toAbstractStructureCompartment when {
not self.getType().oclIsUndefined();
}{
}
mapping inout Shape::addCommentDecoration() when {
self.type = 'Comment_Shape' and self.diagram.type = self.getDiagramType()
} {
self.children += object DecorationNode{
type := 'Comment_BodyLabel';
}
}
mapping inout Shape::addConstraintDecoration() when {
self.type = 'Constraint_Shape' and self.diagram.type = self.getDiagramType()
} {
self.children += object DecorationNode{
type := 'Constraint_BodyLabel'; //Constraint specification
}
}
/***** Nodes **********/
mapping UMLShape::toPapyrusShape() : Shape inherits Shape::toPapyrusShape when {
not self.getType().oclIsUndefined()
}{
}
/****** Connector Labels ******/
mapping BasicDecorationNode::toConnectorLabel() : DecorationNode inherits Node::toPapyrusConnectorLabel when {
not self.getType().oclIsUndefined() and (
self.type = 'ToMultiplicityLabel' or
self.type = 'ToRoleLabel' or
self.type = 'FromMultiplicityLabel' or
self.type = 'FromRoleLabel' or
self.type = 'NameLabel' or
self.type = 'KindLabel'
)
}{
}
/****** Compartments *******/
mapping BasicDecorationNode::toLabel() : DecorationNode inherits Node::toPapyrusNode when {
not self.getType().oclIsUndefined() and
self.element.oclIsKindOf(uml::NamedElement) and
self.type = 'Name'
}{
}
mapping BasicSemanticCompartment::toListCompartment() : BasicCompartment inherits Node::toPapyrusNode, DrawerStyle::toDrawerStyle when {
self.type.endsWith('Compartment') and not self.getType().oclIsUndefined()
}{
}
mapping uml::State::fillTransition(node : BasicSemanticCompartment) : Sequence(Node) when {
node.type='';
}{
init {
result := self.incoming->selectByKind(Transition).map toTransitionIn(node)->asSequence();
}
}
mapping uml::State::fillBehavior(node : BasicSemanticCompartment) : Sequence(Node) when {
node.type='';
}{
init {
result := self.entry->selectByKind(Behavior).map toBehaviorIn(node)->asSequence();
}
}
mapping Transition::toTransitionIn(node : Node) : Shape inherits Element::toCompartmentEntry {
result.type := 'Transition_InternalTransitionLabel';
}
mapping Behavior::toBehaviorIn(node : Node) : Shape inherits Element::toCompartmentEntry {
result.type := 'Behavior_EntryBehaviorLabel';
}
/******* Edges ********/
mapping UMLConnector::toPapyrusConnector() : Connector inherits Connector::toPapyrusConnector when {
self.type = '' and
not self.getType().oclIsUndefined() and (
self.element.oclIsTypeOf(Transition)or
self.element.oclIsTypeOf(Generalization)
)
}{
result.styles := self.map toFontStyle();
}
mapping UMLConnector::toCommentLink() : Connector inherits Connector::toCommentLink when{
self.type='Reference'
}{
result.type :='Comment_AnnotatedElementEdge';
result.bendpoints := self.bendpoints.map toBendpoint(self.diagram);
result.sourceAnchor := object IdentityAnchor{};
}
mapping UMLConnector::toConstraintLink() : Connector inherits Connector::toPapyrusConnector when{
self.type='Reference' and (
self.source.element.oclIsTypeOf(Constraint) or
self.target.element.oclIsKindOf(Constraint)
)
}{
result.type :='Constraint_ConstrainedElementEdge';
result.bendpoints := self.bendpoints.map toBendpoint(self.diagram);
result.sourceAnchor := object IdentityAnchor{};
}
/****** Element Type queries ******/
query View::getNodeType(element : Element) : String {
return
if element.oclIsTypeOf(Comment) then 'Comment_Shape'
elif element.oclIsTypeOf(FinalState) then 'FinalState_Shape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::join then 'Pseudostate_JoinShape'
elif element.oclIsTypeOf(State) then 'State_Shape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::shallowHistory then 'Pseudostate_ShallowHistoryShape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::terminate then 'Pseudostate_TerminateShape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::choice then 'Pseudostate_ChoiceShape'
elif element.oclIsTypeOf(Constraint) then 'Constraint_Shape'
elif element.oclIsTypeOf(StateMachine) then 'StateMachine_Shape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::fork then 'Pseudostate_ForkShape'
elif element.oclIsTypeOf(Region) then 'Region_Shape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::junction then 'Pseudostate_JunctionShape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::deepHistory then 'Pseudostate_DeepHistoryShape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::initial then 'Pseudostate_InitialShape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::entryPoint then 'Pseudostate_EntryPointShape'
elif element.oclIsTypeOf(Pseudostate) and element.oclAsType(Pseudostate).kind = PseudostateKind::exitPoint then 'Pseudostate_ExitPointShape'
elif element.oclIsTypeOf(ConnectionPointReference) then 'ConnectionPointReference_Shape'
else self.fail()
endif;
}
query View::getDecorationType(element : Element) : String{
var res := self.doGetDecorationType(element);
/*log('Get papyrus ID for'+ self.element.eClass().name+', '+self.type);
log(res);
if self.container().oclIsKindOf(Node) then
log('IsNode')
else
log('IsEdge')
endif;*/
return res;
}
query View::doGetDecorationType(element : Element) : String{
return if self.container().oclIsKindOf(Node) then {
return if element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_ChoiceFloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_ExitPointFloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_ShallowHistoryFloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_JoinFloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_InitialFloatingNameLabel';
}
elif element.oclIsTypeOf(Region) then
return switch {
case (self.type = 'Region' or self.type = '') 'Region_SubvertexCompartment';
}
elif element.oclIsTypeOf(ConnectionPointReference) then
return switch {
case (self.type = 'Name') 'ConnectionPointReference_NameLabel';
}
elif element.oclIsTypeOf(State) then
return switch {
case (self.type = 'Name') 'State_NameLabel';
}
elif element.oclIsTypeOf(FinalState) then
return switch {
case (self.type = 'Name') 'FinalState_FloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_DeepHistoryFloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_TerminateFloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_ForkFloatingNameLabel';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_EntryPointFloatingNameLabel';
}
elif element.oclIsTypeOf(StateMachine) then
return switch {
case (self.type = 'Name') 'StateMachine_NameLabel';
case (self.type = 'StructureCompartment') 'StateMachine_RegionCompartment';
}
elif element.oclIsTypeOf(Pseudostate) then
return switch {
case (self.type = 'Name') 'Pseudostate_JunctionFloatingNameLabel';
}
endif
} else {
return if element.oclIsTypeOf(Transition) then
return switch {
case (self.type='Name') 'Transition_NameLabel';
case (self.type = 'NameLabel') 'Transition_NameLabel';
}
endif
} endif;
}
query View::getEdgeType(element : Element) : String {
return
if self.type = 'Reference' then '' /* Constraint/Comment links handled separately */
elif element.oclIsTypeOf(Transition) then 'Transition_Edge'
elif element.oclIsTypeOf(Generalization) then 'Generalization_Edge'
else self.fail()
endif;
}