| /***************************************************************************** |
| * Copyright (c) 2016 CEA LIST. |
| * |
| * 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: |
| * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation |
| *****************************************************************************/ |
| |
| import Rpy2PapyrusSemanticElements; |
| import RpyUtils; |
| import SysMLRpyUtils; |
| import RpyToPapyrusDiagamCommon; |
| import org.eclipse.papyrus.interoperability.rpy.blackboxes.Rpy2PapyrusNotationBlackboxes; |
| import org.eclipse.papyrus.interoperability.rpy.blackboxes.sysml11.diagrams.InternalBlockDiagramFixLayoutBlackboxes; |
| |
| modeltype umlrpy "strict" uses 'http://www.eclipse.org/Papyrus/UMLRpy/1.0.0'; |
| modeltype notation "strict" uses 'http://www.eclipse.org/gmf/runtime/1.0.2/notation'; |
| modeltype uml "strict" uses 'http://www.eclipse.org/uml2/5.0.0/UML'; |
| modeltype sysml11 "strict" uses 'http://www.eclipse.org/papyrus/0.7.0/SysML'; |
| modeltype ecore "strict" uses 'http://www.eclipse.org/emf/2002/Ecore'; |
| modeltype UMLPrimitivesTypes "strict" uses 'http://www.eclipse.org/uml2/5.0.0/Types' ; |
| |
| |
| /** |
| * |
| * This transformation manages the SysML 1.1 Internal Block Diagram |
| * TODO in this transfo : |
| * floating label location |
| * managing comment link on link |
| */ |
| transformation SysML11InternalBlockDiagram(in semantics : umlrpy, out graphics : notation, inout model:uml, in Sysml11Profile:sysml11, in primitives:UMLPrimitivesTypes) |
| access transformation Rpy2PapyrusSemanticElements(in inModel:umlrpy, out outModel:uml, in primitives:UMLPrimitivesTypes) |
| extends Rpy2PapyrusSemanticElements(in inModel:umlrpy, out outModel:uml, in primitives:UMLPrimitivesTypes) |
| { |
| //nothing to do here |
| } |
| |
| |
| /** |
| * |
| * Map a Rpy IBD Diagram with a Papyrus SysML 1.1 IBD Diagram |
| */ |
| mapping rpymetamodel::IDiagram::iDiagramToSysML11InternalBlockDiagram(rpyProject:IProject):Diagram when{self.isUserModelDiagram() and self.isSysMLInternalBlockDiagram()}{ |
| //1. creating the diagram object |
| init { |
| //we are looking for the owner of the diagram |
| var owner:EObject; |
| var iDiagramOwner:ecore::EObject:=self[EObject].eContainer()![EObject]; |
| if(iDiagramOwner.oclIsKindOf(umlrpy::IClass)){ |
| owner:= iDiagramOwner.resolveIn(ecore::EObject::generalMappingToUMLElement, uml::Element)![EObject]; |
| }; |
| result:=self.map createAndInitDiagram(rpyProject,getPapyrusDiagramType(), owner, owner); |
| } |
| |
| //1. find some objects |
| var cgiClassChart:CGIClassChart:=self.graphicChart->oclAsSet().selectByType(CGIClassChart)->any(true); |
| var cgiClass:CGIClass:=cgiClassChart.graphElements->selectByType(CGIClass)->any(true); |
| var cgiDiagramFrame:CGIDiagramFrame:=cgiClassChart.graphElements->selectByType(CGIDiagramFrame)->any(true); |
| |
| //2. as it is an IBD, we must represent the owner in the diagram. This is the Rpy Frame |
| var rootBlockShape:Shape= object Shape{ |
| type:="shape_sysml_block_as_composite"; |
| children+= object DecorationNode { type:="label_sysml_block_name"}; |
| layoutConstraint:=object Bounds{ |
| x:=cgiDiagramFrame.get_X_Position(); |
| y:=cgiDiagramFrame.get_Y_Position(); |
| width:=cgiDiagramFrame.get_Width(); |
| height:=cgiDiagramFrame.get_Height() |
| }; |
| }; |
| |
| var blockCompartmentStructure:BasicCompartment:= object BasicCompartment { |
| type:="compartment_sysml_structure"; |
| styles+= object TitleStyle{}; |
| }; |
| rootBlockShape.children+=blockCompartmentStructure; |
| children+=rootBlockShape; |
| |
| //3. map the children of the compartment |
| blockCompartmentStructure.children+=cgiClassChart.graphElements->select(a | a.isAllowedAsCompartmentChildren(blockCompartmentStructure)).map graphElementsTypeToIBDShapes(cgiClassChart,cgiClass->asSequence()); |
| |
| //4. map the affixed child node of the compartment |
| rootBlockShape.children+=cgiClassChart.graphElements->select(a | a.isAllowedAsAffixedChildNode(rootBlockShape)).map graphElementsTypeToIBDShapes(cgiClassChart, cgiDiagramFrame->asSequence()); |
| |
| //5. map the edges of the diagram |
| edges+=cgiClassChart.graphElements.map graphElementsTypeToIBDEdges(cgiClassChart, cgiDiagramFrame->asSequence()).oclAsType(notation::Edge); |
| |
| fixLayout(result); |
| } |
| |
| /** |
| * Returns the type of the diagram to create |
| */ |
| query getPapyrusDiagramType():String{ |
| return 'InternalBlock'; |
| }; |
| |
| /** |
| * This method allows to map comment link |
| * |
| */ |
| mapping rpymetamodel::CGIAnchor::graphElementsTypeToIBDCommentLink(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Connector when {self.getLinkSourceView()<>null and self.getLinkTargetView()<>null}{ |
| type:="Comment_AnnotatedElementEdge"; |
| source:=self.getLinkSourceView(); |
| target:=self.getLinkTargetView(); |
| var sourceNode:M_pRootType:=self.m_pSource; |
| var targetNode:M_pRootType:=self.m_pTarget; |
| addAnchorsAndBendpoints(self,result); |
| |
| //manage connector routing |
| routing:=self.oclAsType(GraphElementsType).getConnectorRouting(); |
| eAnnotations+=createCSSForceValue("routing"); |
| } |
| |
| |
| /** |
| * |
| * This method allows to map the connector link |
| */ |
| mapping rpymetamodel::CGIObjectLink::graphElementsTypeToIBDConnector(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Connector when {self.getLinkSourceView()<>null and self.getLinkTargetView()<>null}{ |
| type:="link_uml_connector"; |
| source:=self.getLinkSourceView(); |
| target:=self.getLinkTargetView(); |
| element:= self.m_pModelObject.resolveoneIn(umlrpy::IObjectLink::iObjectLinkToUMLElement).oclAsType(EObject); |
| |
| addAnchorsAndBendpoints(self,result); |
| |
| children+=object DecorationNode{ |
| type:="linklabel_uml_appliedstereotype"; |
| layoutConstraint:=object Location{ |
| y:=-30; //TODO : a dummy value |
| }; |
| }; |
| |
| |
| //managing the name label of the connector |
| // var nameText:CGIText:=self.m_rpn; |
| children+=object DecorationNode{ |
| type:="linklabel_uml_connector_label"; |
| layoutConstraint:=object Location{ |
| y:=-10; //TODO : a dummy value |
| }; |
| }; |
| |
| //manage connector routing |
| routing:=self.oclAsType(GraphElementsType).getConnectorRouting(); |
| eAnnotations+=createCSSForceValue("routing"); |
| } |
| |
| |
| |
| //TODO : calling resolve method could not work in soem case : if we are mapping a link linked to another link not yet mapped -> we will not able to resolve it! |
| //TODO : manage link linked to an other link (comment link for example) |
| query umlrpy::CGIAnchor::getLinkSourceView():View{ |
| var source:View:=self.m_pSource![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDShapes, Shape)![View]; |
| if(source=null){ |
| // source:=self.m_pSource![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDEdges, Connector)![View]; |
| }; |
| return source; |
| } |
| |
| query umlrpy::CGIAnchor::getLinkTargetView():View{ |
| var target:View:=self.m_pTarget![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDShapes, Shape)![View]; |
| if(target=null){ |
| // target:=self.m_pTarget![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDEdges, Connector)![View]; |
| }; |
| return target |
| } |
| |
| query umlrpy::CGIObjectLink::getLinkSourceView():View{ |
| var source:View:=self.m_pSource![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDShapes, Shape)![View]; |
| if(source=null){ |
| // source:=self.m_pSource![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDEdges, Connector)![View]; |
| }; |
| return source; |
| } |
| |
| query umlrpy::CGIObjectLink::getLinkTargetView():View{ |
| var target:View:=self.m_pTarget![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDShapes, Shape)![View]; |
| if(target=null){ |
| // target:=self.m_pTarget![M_pRootType].resolveIn(umlrpy::GraphElementsType::graphElementsTypeToIBDEdges, Connector)![View]; |
| }; |
| return target |
| } |
| |
| /** |
| * This mapping take GraphElementsType and returns Shape. |
| * @param |
| * cgiClassChart : the class chart of the diagram, it is useful to find child to create for the created element |
| * @param |
| * rpyAllowedParent : the list of the allowed Rpy parent to manage the object. |
| * if the Rpy parent is not in this list, the object won't be mapped |
| * |
| */ |
| mapping rpymetamodel::GraphElementsType::graphElementsTypeToIBDShapes(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Shape disjuncts |
| rpymetamodel::CGIAnnotation::CGIAnnotationToCommentCN, |
| rpymetamodel::CGIObjectInstance::CGIObjectInstanceIBDBlockProperty, |
| rpymetamodel::CGIGenericElement::CGIGenericElementToIBDBlockProperty, |
| rpymetamodel::CGIPortConnector::CGIPortConnectorToIBDPort |
| {} |
| |
| |
| mapping rpymetamodel::GraphElementsType::graphElementsTypeToIBDEdges(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Edge disjuncts |
| rpymetamodel::CGIObjectLink::graphElementsTypeToIBDConnector, |
| rpymetamodel::CGIAnchor::graphElementsTypeToIBDCommentLink |
| {} |
| |
| mapping rpymetamodel::CGIPortConnector::CGIPortConnectorToIBDPort(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Shape when {self.oclIsTypeOf(CGIPortConnector) and rpyAllowedParent->includes(self.m_pParent.oclAsType(GraphElementsType))}{ |
| type:="shape_sysml_flowport_as_affixed"; |
| children+= object DecorationNode{ |
| type:="affixedlabel_sysml_flowport_label"; |
| layoutConstraint:= object Location{ |
| x:=30; //TODO |
| }; |
| }; |
| children+= object DecorationNode{ |
| type:="affixedlabel_uml_appliedstereotype"; |
| layoutConstraint:= object Location{ |
| x:=30; //TODO |
| }; |
| }; |
| layoutConstraint:= object Bounds{ |
| x:=getX(self); |
| y:=getY(self); |
| //width:=getRectangleWidth(self); |
| //height:=getRectangleHeight(self); |
| //result of calculus was wrong for port size and moreover this calculus is useless for port. |
| width:=20; |
| height:=20; |
| |
| }; |
| |
| var semanticElementRpy:IRelation:=self.m_pModelObject; |
| element:=self.m_pModelObject.resolveoneIn(umlrpy::IRelation::iRelationToUMLElement).oclAsType(EObject); |
| } |
| |
| /** |
| * This method maps a CGIObject on a BlockProperty |
| * @param |
| * cgiClassChart |
| * @param |
| * rpyAllowedParent |
| * |
| */ |
| mapping rpymetamodel::CGIObjectInstance::CGIObjectInstanceIBDBlockProperty(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Shape when {self.m_pModelObject.oclIsTypeOf(IPart) and self.oclIsTypeOf(CGIObjectInstance) and rpyAllowedParent->includes(self.m_pParent.oclAsType(GraphElementsType))}{ |
| init{ |
| //1. create the shape |
| result:=self.graphElementTypeToIBDBlockProperty(cgiClassChart, rpyAllowedParent); |
| } |
| |
| //2. set the represented element |
| var resolvedE:=self.m_pModelObject.resolveoneIn(umlrpy::IPart::iPartToUMLElement); |
| element:=resolvedE.oclAsType(EObject); |
| } |
| |
| /** |
| * Returns true when the graph element can be used as an affixed child node in Papyrus Diagram |
| */ |
| query umlrpy::GraphElementsType::isAllowedAsAffixedChildNode(shape:Shape):Boolean{ |
| return self.oclIsTypeOf(CGIPortConnector); |
| } |
| |
| /** |
| * Returns true when the graph element can be set as a children of a given compartment |
| */ |
| query umlrpy::GraphElementsType::isAllowedAsCompartmentChildren(cpt:BasicCompartment):Boolean{ |
| return not self.oclIsTypeOf(CGIPortConnector); |
| } |
| |
| |
| mapping rpymetamodel::CGIGenericElement::CGIGenericElementToIBDBlockProperty(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Shape when {self.m_pModelObject.oclIsTypeOf(IAssociationEnd) and self.m_pModelObject.oclAsType(IAssociationEnd).inverse.oclIsUndefined() and rpyAllowedParent->includes(self.m_pParent.oclAsType(GraphElementsType))}{ |
| init{ |
| //1. create the shape |
| result:=self.graphElementTypeToIBDBlockProperty(cgiClassChart, rpyAllowedParent); |
| } |
| |
| //2. set the represented element |
| var representedElement:=self.m_pModelObject; |
| var assoEnd:IAssociationEnd:=self.m_pModelObject.oclAsType(IAssociationEnd); |
| var resolvedE:Association=representedElement.resolveoneIn(umlrpy::IAssociationEnd::iAssociationEndToUMLAssociation); |
| var resolvedE2:Property:=resolvedE.memberEnd->select(endd | endd.oclIsKindOf(Property))->select(p | not p.oclAsType(Property).owner.oclIsKindOf(Association))->any(true); |
| element:=resolvedE2.oclAsType(EObject); |
| } |
| |
| /** |
| * |
| * Helper used to create the Block Property Shape |
| */ |
| helper rpymetamodel::GraphElementsType::graphElementTypeToIBDBlockProperty(cgiClassChart:CGIClassChart, rpyAllowedParent:Sequence(GraphElementsType)):Shape{ |
| var localShape:Shape:=object Shape{ |
| type:="shape_sysml_blockproperty_as_composite"; |
| }; |
| |
| localShape.children+= object DecorationNode{ |
| type:="label_uml_property_label"; |
| }; |
| var basicCpt:BasicCompartment:=object BasicCompartment{ |
| type:="compartment_sysml_blockproperty_structure"; |
| styles+=object TitleStyle{}; |
| }; |
| localShape.children+=basicCpt; |
| localShape.layoutConstraint:= object Bounds{ x:=getX(self); y:=getY(self); width :=getRectangleWidth(self); height := getRectangleHeight(self)}; |
| |
| basicCpt.children+=cgiClassChart.graphElements->select(a | a.isAllowedAsCompartmentChildren(basicCpt)).map graphElementsTypeToIBDShapes(cgiClassChart, self->asSequence()); |
| localShape.children+=cgiClassChart.graphElements->select(a | a.isAllowedAsAffixedChildNode(localShape)).map graphElementsTypeToIBDShapes(cgiClassChart, self->asSequence()); |
| return localShape; |
| } |