| /***************************************************************************** |
| * Copyright (c) 2017 CEA LIST 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: |
| * Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Initial API and implementation |
| *****************************************************************************/ |
| |
| import org.eclipse.papyrus.interoperability.common.blackboxes.ecore.EcoreHelper; |
| import org.eclipse.papyrus.interoperability.sysml14.sysml.blackboxes.notation.NotationBlackboxHelper; |
| import org.eclipse.papyrus.interoperability.sysml14.sysml.SysMLDiagramsUtils; |
| import org.eclipse.papyrus.interoperability.sysml14.sysml.SysMLDiagramsConstants; |
| import org.eclipse.papyrus.interoperability.sysml14.sysml.SysMLUtils; |
| |
| 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 ecore "strict" uses 'http://www.eclipse.org/emf/2002/Ecore'; |
| modeltype viewpoint "strict" uses 'http://www.eclipse.org/papyrus/infra/viewpoints/configuration'; |
| modeltype SysML11 "strict" uses 'http://www.eclipse.org/papyrus/0.7.0/SysML'; |
| modeltype SysML14 "strict" uses 'http://www.eclipse.org/papyrus/sysml/1.4/SysML'; |
| modeltype nattable "strict" uses 'http://www.eclipse.org/papyrus/nattable/model'; |
| |
| |
| transformation SysMLRequirementDiagram(in blockDefinitionViewpoint : viewpoint, in internalBlockViewpoint : viewpoint, in parametricViewpoint : viewpoint, in requirementViewpoint : viewpoint, in umlFile : UML, in inS14Profile : SysML14, in requirementNatTableS11 : nattable, in allocationNatTableS11 : nattable, in requirementNatTableS14 : nattable, in allocationNatTableS14 : nattable, in requirementTableViewPoint : viewpoint, in allocationTableViewPoint : viewpoint, inout notationFile : notation); |
| |
| // Define needed constants |
| property diagramName:String = "RequirementDiagram"; |
| property diagramConfigurationName:String = "SysML 1.4 Requirement"; |
| |
| property model:UML::Model = umlFile.rootObjects()[uml::Model]->any(true); |
| property rootDiagram:notation::Diagram; |
| |
| property childrenToRemove:OrderedSet(notation::View); |
| |
| mapping notation::Diagram::fromSysML11RequirementDiagram() : notation::Diagram when {self.type=diagramName} { |
| init{ |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| var existingEdges:OrderedSet(notation::Edge) := self.edges; |
| result := self; |
| rootDiagram := result; |
| result.edges := object OrderedSet(notation::Edge){}; |
| result.edges := existingEdges->map fromSysML11Edge(); |
| result.children := object OrderedSet(notation::Node){}; |
| result.children := existingChildren->map fromSysML11Shape(result); |
| result.children[notation::Shape]->map fromSysML11ShapeToSysML14Edge(result); |
| } |
| type := "PapyrusUMLClassDiagram"; |
| |
| // Create the annotation for versionning |
| var model:UML::Model := umlFile.rootObjects()[uml::Model]->any(true); |
| result.eAnnotations += model.createEAnnotationForVersioning(); |
| |
| // Modify or create the compatibility version |
| setOrCreateCompatibilityVersion(result); |
| |
| // Add the viewpoint configuration to the papyrus view style |
| addPapyrusViewStyleConfiguration(result, model, getRequirementPapyrusDiagramConfiguration()); |
| |
| // Remove the needed children |
| childrenToRemove->forEach(childToRemove){ |
| var parent:ecore::EObject := childToRemove.oclAsType(ecore::EObject).eContainer(); |
| if (parent.oclIsKindOf(notation::View)) { |
| var parentView:notation::View := parent.oclAsType(notation::View); |
| removeFromOwnerView(parentView, childToRemove); |
| }; |
| }; |
| } |
| |
| // Get the requirement papyrus diagram configuration from the viewpoint file |
| helper getRequirementPapyrusDiagramConfiguration() : viewpoint::PapyrusDiagram { |
| return requirementViewpoint.objects()->selectByType(viewpoint::PapyrusDiagram)->any(curr | curr.name = diagramConfigurationName); |
| } |
| |
| // Nodes ans shapes management |
| mapping notation::Node::fromSysML11Shape(parent:notation::View) : notation::Node disjuncts |
| notation::BasicCompartment::fromSysML11BasicCompartment, |
| notation::DecorationNode::fromSysML11DecorationNode, |
| notation::Shape::fromSysML11StereotypeComment, |
| notation::Shape::fromSysML11RequirementAsClassifier, |
| notation::Shape::fromSysML11ViewPackageAsClass, |
| notation::Shape::fromSysML11PackageShapeAsModel, // Must be done before PackageShapeAsPackage |
| notation::Shape::fromSysML11PackageShapeAsPackage, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsCommunicationPath, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsGeneralizationSet, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsComponent, // Must be done before Class |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsClass, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsEnumeration, // Must be done before DataType |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsPrimitiveType, // Must be done before DataType |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsDataType, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsDurationObservation, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsInformationItem, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsInterface, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsInstanceSpecification, |
| notation::Shape::fromSysML11NamedElementDefaultShapeAsSignal, |
| notation::Shape::fromSysML11DefaultShape |
| {} |
| |
| mapping notation::Shape::fromSysML11ViewPackageAsClass(parent:notation::View) : notation::Shape when {self.oclIsTypeOf(notation::Shape) and self.type = PACKAGE_SHAPE_SYSML14 and self.element.oclIsKindOf(UML::Class)} { |
| init { |
| result := self; |
| } |
| type := CLASS_SHAPE_SYSML14; |
| |
| // Remove the existing children |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| children := object OrderedSet(notation::Node){}; |
| |
| var isCN:Boolean := not parent.oclIsTypeOf(notation::Diagram); |
| |
| // Search if the name label is existing |
| existingChildren->forEach(existingChild){ |
| if (existingChild.type = PACKAGE_NAME_LABEL_DECORATIONNODE_SYSML14 or existingChild.type = PACKAGE_NAME_LABEL_DECORATIONNODE_CN_SYSML14) { |
| if (isCN) { |
| existingChild.type := CLASS_NAME_LABEL_DECORATIONNODE_CN_SYSML14; |
| } else { |
| existingChild.type := CLASS_NAME_LABEL_DECORATIONNODE_SYSML14; |
| }; |
| children += existingChild; |
| } elif (existingChild.type = COMPARTMENT_SHAPE_DISPLAY) { |
| children += existingChild; |
| }; |
| }; |
| |
| // Create and set the default DecorationNodes |
| children += createDefaultFloatingNameLabelDecorationNode(CLASS_FLOATING_LABEL_DECORATIONNODE_SYSML14); |
| |
| // Create and set the default BasicCompartments |
| children += createDefaultBasicCompartement(CLASS_ATTRIBUTE_COMPARTMENT_SYSML14); |
| children += createDefaultBasicCompartement(CLASS_OPERATION_COMPARTMENT_SYSML14); |
| children += createDefaultBasicCompartement(CLASS_NESTEDCLASSIFIER_COMPARTMENT_SYSML14); |
| } |
| |
| mapping notation::Shape::fromSysML11PackageShapeAsModel(parent:notation::View) : notation::Shape when {self.oclIsTypeOf(notation::Shape) and self.element.oclIsKindOf(UML::Model)} { |
| init { |
| result := self; |
| } |
| var isCN:Boolean := not parent.oclIsTypeOf(notation::Diagram); |
| |
| // Remove the existing children |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| children := object OrderedSet(notation::Node){}; |
| |
| var typeLabel:String = MODEL_SHAPE_SYSML14; |
| var modelNameLabel:String := MODEL_NAME_LABEL_DECORATIONNODE_SYSML14; |
| var modelPackagedElementCompartment:String := MODEL_PACKAGEDELEMENT_COMPARTMENT_SYSML14; |
| |
| // If the shape is not in the diagram, this is a Child node |
| if (isCN) { |
| typeLabel := MODEL_SHAPE_CN_SYSML14; |
| modelNameLabel := MODEL_NAME_LABEL_DECORATIONNODE_CN_SYSML14; |
| modelPackagedElementCompartment:= MODEL_PACKAGEDELEMENT_COMPARTMENT_CN_SYSML14; |
| }; |
| |
| type := typeLabel; |
| |
| if(self.type = NAMEDELEMENT_DEFAULTSHAPE){ |
| children += createDefaultNameLabelDecorationNode(modelNameLabel); |
| var packageElementCompartment:notation::BasicCompartment := createDefaultBasicCompartement(modelPackagedElementCompartment); |
| packageElementCompartment.styles += object notation::TitleStyle{}; |
| packageElementCompartment.layoutConstraint := object notation::Bounds{}; |
| children += packageElementCompartment; |
| }else{ |
| // Search if the packaged element compartment is existing |
| existingChildren->forEach(existingChild){ |
| if (existingChild.type = PACKAGE_NAME_LABEL_DECORATIONNODE_SYSML14 or existingChild.type = PACKAGE_NAME_LABEL_DECORATIONNODE_CN_SYSML14) { |
| existingChild.type := modelNameLabel; |
| setPapyrusCSSForceValueVisible(existingChild, TRUE); |
| children += existingChild; |
| } elif (existingChild.type = PACKAGE_PACKAGEDELEMENT_COMPARTMENT_SYSML14 or existingChild.type = PACKAGE_PACKAGEDELEMENT_COMPARTMENT_CN_SYSML14) { |
| existingChild.type := modelPackagedElementCompartment; |
| setPapyrusCSSForceValueVisible(existingChild, TRUE); |
| setShowTitle(existingChild, true); |
| // Map the existing children shapes |
| existingChild.children := existingChild.children->map fromSysML11Shape(result); |
| existingChild.children[notation::Shape]->map fromSysML11ShapeToSysML14Edge(existingChild); |
| children += existingChild; |
| } elif (existingChild.type = COMPARTMENT_SHAPE_DISPLAY) { |
| children += existingChild; |
| }; |
| }; |
| }; |
| } |
| |
| mapping notation::Shape::fromSysML11PackageShapeAsPackage(parent:notation::View) : notation::Shape when {self.oclIsTypeOf(notation::Shape) and self.type = PACKAGE_SHAPE_SYSML14 and self.element.oclIsKindOf(UML::Package)} { |
| init { |
| result := self; |
| } |
| |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| children := object OrderedSet(notation::Node){}; |
| children := existingChildren->map fromSysML11Shape(result); |
| |
| var isCN:Boolean := not parent.oclIsTypeOf(notation::Diagram); |
| |
| // Search if the packaged element compartment is existing |
| existingChildren->forEach(existingChild){ |
| if (existingChild.type = PACKAGE_PACKAGEDELEMENT_COMPARTMENT_SYSML14 or existingChild.type = PACKAGE_PACKAGEDELEMENT_COMPARTMENT_CN_SYSML14) { |
| setPapyrusCSSForceValueVisible(existingChild, TRUE); |
| setShowTitle(existingChild, true); |
| // Map the existing children shapes |
| existingChild.children := existingChild.children->map fromSysML11Shape(result); |
| existingChild.children[notation::Shape]->map fromSysML11ShapeToSysML14Edge(existingChild); |
| } |
| }; |
| } |
| |
| mapping notation::Shape::fromSysML11RequirementAsClassifier(parent:notation::View) : notation::Shape when {self.oclIsTypeOf(notation::Shape) and self.type = REQUIREMENT_AS_CLASSIFIER_SYSML11} { |
| init { |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| result := self; |
| result.children := object OrderedSet(notation::Node){}; |
| result.children := existingChildren->map fromSysML11Shape(result); |
| } |
| var isCN:Boolean := not parent.oclIsTypeOf(notation::Diagram); |
| |
| // If the shape is not in the diagram, this is a Child node |
| if (not isCN) { |
| type := CLASS_SHAPE_SYSML14; |
| |
| // Create the FloatingNameLabel decoration node with its default layout constraint |
| children += createDefaultFloatingNameLabelDecorationNode(CLASS_FLOATING_LABEL_DECORATIONNODE_SYSML14); |
| |
| // Create and set the default BasicCompartments |
| children += createDefaultBasicCompartement(CLASS_ATTRIBUTE_COMPARTMENT_SYSML14); |
| children += createDefaultBasicCompartement(CLASS_OPERATION_COMPARTMENT_SYSML14); |
| children += createDefaultBasicCompartement(CLASS_NESTEDCLASSIFIER_COMPARTMENT_SYSML14); |
| } else { |
| type := CLASS_SHAPE_CN_SYSML14; |
| |
| // Create the FloatingNameLabel decoration node with its default layout constraint |
| children += createDefaultFloatingNameLabelDecorationNode(CLASS_FLOATING_LABEL_DECORATIONNODE_CN_SYSML14); |
| |
| // Create and set the default BasicCompartments |
| children += createDefaultBasicCompartement(CLASS_ATTRIBUTE_COMPARTMENT_CN_SYSML14); |
| children += createDefaultBasicCompartement(CLASS_OPERATION_COMPARTMENT_CN_SYSML14); |
| children += createDefaultBasicCompartement(CLASS_NESTEDCLASSIFIER_COMPARTMENT_CN_SYSML14); |
| }; |
| } |
| |
| mapping notation::Shape::fromSysML11NamedElementDefaultShapeAsCommunicationPath(parent:notation::View) : notation::Shape when {self.oclIsTypeOf(notation::Shape) and self.element.oclIsTypeOf(UML::CommunicationPath)} { |
| init{ |
| result := self; |
| } |
| childrenToRemove += result; |
| } |
| |
| mapping notation::Shape::fromSysML11NamedElementDefaultShapeAsGeneralizationSet(parent:notation::View) : notation::Shape when {self.oclIsTypeOf(notation::Shape) and self.element.oclIsTypeOf(UML::GeneralizationSet)} { |
| init{ |
| result := self; |
| } |
| childrenToRemove += result; |
| } |
| |
| mapping notation::Shape::fromSysML11StereotypeComment(parent:notation::View) : notation::Shape when {self.type = STEREOTYPE_COMMENT} { |
| init { |
| result := self; |
| } |
| |
| childrenToRemove += result; |
| } |
| |
| mapping notation::Shape::fromSysML11DefaultShape(parent:notation::View) : notation::Shape when {self.oclIsTypeOf(notation::Shape)} { |
| init { |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| result := self; |
| result.children := object OrderedSet(notation::Node){}; |
| result.children := existingChildren->map fromSysML11Shape(result); |
| } |
| } |
| |
| mapping notation::DecorationNode::fromSysML11DecorationNode(parent:notation::View) : notation::DecorationNode disjuncts |
| notation::DecorationNode::fromSysML11StereotypeLabel, |
| notation::DecorationNode::fromSysML11DecorationNodeDefault |
| {} |
| |
| mapping notation::DecorationNode::fromSysML11StereotypeLabel(parent:notation::View) : notation::DecorationNode when {self.oclIsTypeOf(notation::DecorationNode) and self.type = STEREOTYPE_LABEL_DECORATION_NODE}{ |
| init{ |
| result := self; |
| if(self.element.oclIsKindOf(UML::Stereotype)){ |
| var stereotype:UML::Stereotype := self.element.oclAsType(UML::Stereotype).toSysML14Stereotype(inS14Profile.objectsOfType(UML::Stereotype)); |
| if (stereotype.oclIsUndefined()) { |
| // The stereotype was not find in SysML1.4, remove the decoration node |
| childrenToRemove += result; |
| } else { |
| result.element := stereotype.oclAsType(ecore::EObject); |
| } |
| }; |
| } |
| } |
| |
| mapping notation::DecorationNode::fromSysML11DecorationNodeDefault(parent:notation::View) : notation::DecorationNode when {self.oclIsTypeOf(notation::DecorationNode)} { |
| init{ |
| result := self; |
| setPapyrusCSSForceValueVisible(result, TRUE); |
| } |
| } |
| |
| mapping notation::BasicCompartment::fromSysML11BasicCompartment(parent:notation::View) : notation::BasicCompartment disjuncts |
| notation::BasicCompartment::fromSysML11StereotypeBraceAndCompartment, |
| notation::BasicCompartment::fromSysML11BasicCompartmentDefault |
| {} |
| |
| mapping notation::BasicCompartment::fromSysML11BasicCompartmentDefault(parent:notation::View) : notation::BasicCompartment when {self.oclIsTypeOf(notation::BasicCompartment) and self.type <> REQUIREMENT_IDINFO_COMPARTMENT_SYSML11}{ |
| init{ |
| result := self; |
| setPapyrusCSSForceValueVisible(result, TRUE); |
| setShowTitle(result, true); |
| } |
| } |
| |
| mapping notation::BasicCompartment::fromSysML11StereotypeBraceAndCompartment(parent:notation::View) : notation::BasicCompartment when {self.oclIsTypeOf(notation::BasicCompartment) and (self.type = STEREOTYPE_BRACE_COMPARTMENT or self.type = STEREOTYPE_COMPARTMENT_COMPARTMENT) }{ |
| init{ |
| result := self; |
| if(self.element.oclIsKindOf(UML::Stereotype)){ |
| var stereotype:UML::Stereotype := self.element.oclAsType(UML::Stereotype).toSysML14Stereotype(inS14Profile.objectsOfType(UML::Stereotype)); |
| if (stereotype.oclIsUndefined()) { |
| // The stereotype was not find in SysML1.4, remove the compartment |
| childrenToRemove += result; |
| } else { |
| result.element := stereotype.oclAsType(ecore::EObject); |
| } |
| }; |
| } |
| } |
| |
| // Edges management |
| mapping notation::Edge::fromSysML11Edge() : notation::Edge disjuncts |
| notation::Edge::fromSysML11ConformDependencyAsGeneralization, |
| notation::Edge::fromSysML11RealizationEdgeAsInterfaceRealization, // Must be done before Realization |
| notation::Edge::fromSysML11RealizationEdgeAsSubstitution, // Must be done before Realization |
| notation::Edge::fromSysML11RealizationEdgeAsRealization, |
| notation::Edge::fromSysML11DependencyEdgeAsUsage, |
| notation::Edge::fromSysML11DefaultEdge |
| {} |
| |
| mapping notation::Edge::fromSysML11ConformDependencyAsGeneralization() : notation::Edge when {self.oclIsTypeOf(notation::Edge) and self.type = DEPENDENCY_EDGE_SYSML14 and self.element.oclIsKindOf(UML::Generalization)} { |
| init { |
| result := self; |
| } |
| type := GENERALIZATION_EDGE_SYSML14; |
| |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| children := object OrderedSet(notation::Node){}; |
| |
| existingChildren->forEach(existingChild){ |
| if (existingChild.type = DEPENDENCY_STEREOTYPE_LABEL_DECORATIONNODE_SYSML14) { |
| existingChild.type := GENERALIZATION_STEREOTYPE_LABEL_DECORATIONNODE_SYSML14; |
| setPapyrusCSSForceValueVisible(existingChild, TRUE); |
| children += existingChild; |
| }; |
| }; |
| } |
| |
| mapping notation::Edge::fromSysML11StereotypeCommentLink() : notation::Edge when {self.type = STEREOTYPE_COMMENT_LINK} { |
| init { |
| result := self; |
| } |
| |
| childrenToRemove += result; |
| } |
| |
| mapping notation::Edge::fromSysML11DefaultEdge() : notation::Edge { |
| init { |
| result := self; |
| } |
| } |
| |
| mapping notation::Shape::fromSysML11ShapeToSysML14Edge(inout parent:notation::View) disjuncts |
| notation::Shape::fromSysML11SpecificInformationFlow, |
| notation::Shape::fromSysML11AssociationClass, |
| notation::Shape::fromSysML11Association |
| {} |
| |
| mapping notation::Shape::fromSysML11SpecificInformationFlow(inout parent:notation::View) when {self.oclIsTypeOf(notation::Shape) and not self.element.oclIsUndefined() and self.element.oclIsKindOf(UML::InformationFlow)} { |
| var informationFlow:UML::InformationFlow := self.element.oclAsType(UML::InformationFlow); |
| var informationSource:UML::NamedElement := informationFlow.informationSource->any(true); |
| var informationTarget:UML::NamedElement := informationFlow.informationTarget->any(true); |
| |
| var sourceShape:notation::Shape := parent.children[notation::Shape]->any(curr | not curr.element.oclIsUndefined() and curr.element.oclIsKindOf(UML::NamedElement) and curr.element.oclAsType(UML::NamedElement) = informationSource); |
| |
| var informationFlowEdge := object notation::Connector{ |
| element := self.element; |
| |
| var isSourceCreated:Boolean := false; |
| if (sourceShape.oclIsUndefined()) { |
| sourceShape := createShape(parent, informationSource); |
| var createdBounds:notation::Bounds := object notation::Bounds{}; |
| if (self.layoutConstraint.oclIsKindOf(notation::Bounds)) { |
| createdBounds.x := self.layoutConstraint.oclAsType(notation::Bounds).x; |
| createdBounds.y := self.layoutConstraint.oclAsType(notation::Bounds).y; |
| createdBounds.width := self.layoutConstraint.oclAsType(notation::Bounds).width; |
| createdBounds.height := self.layoutConstraint.oclAsType(notation::Bounds).height; |
| }; |
| sourceShape.oclAsType(notation::Shape).layoutConstraint := createdBounds; |
| isSourceCreated := true; |
| parent.children += sourceShape; |
| }; |
| |
| var targetShape:notation::Shape := parent.children[notation::Shape]->any(curr | not curr.element.oclIsUndefined() and curr.element.oclIsKindOf(UML::NamedElement) and curr.element.oclAsType(UML::NamedElement) = informationTarget); |
| if (targetShape.oclIsUndefined()) { |
| targetShape := createShape(parent, informationTarget); |
| var createdBounds:notation::Bounds := object notation::Bounds{}; |
| if (self.layoutConstraint.oclIsKindOf(notation::Bounds)) { |
| // If the source and the target are created, move the target to 100 |
| var createdX:Integer := self.layoutConstraint.oclAsType(notation::Bounds).x; |
| if (isSourceCreated) { |
| createdX := createdX + 100; |
| }; |
| createdBounds.x := createdX; |
| createdBounds.y := self.layoutConstraint.oclAsType(notation::Bounds).y; |
| createdBounds.width := self.layoutConstraint.oclAsType(notation::Bounds).width; |
| createdBounds.height := self.layoutConstraint.oclAsType(notation::Bounds).height; |
| }; |
| targetShape.oclAsType(notation::Shape).layoutConstraint := createdBounds; |
| parent.children += targetShape; |
| }; |
| |
| source := sourceShape; |
| target := targetShape; |
| }; |
| createBendpointsForInformationFlow(informationFlowEdge); |
| createDefaultInformationFlowDecorationNodes(informationFlowEdge); |
| rootDiagram.edges += informationFlowEdge; |
| |
| removeFromOwnerView(parent, self); |
| } |
| |
| mapping notation::Shape::fromSysML11Association(inout parent:notation::View) when {self.oclIsTypeOf(notation::Shape) and not self.element.oclIsUndefined() and self.element.oclIsKindOf(UML::Association)} { |
| |
| var association:UML::Association := self.element.oclAsType(UML::Association); |
| // Get the [0] and [1] member end for the source and target properties |
| var sourceProperty:UML::Property := association.memberEnd->any(true); |
| var targetProperty:UML::Property := association.memberEnd->any(curr | curr <> sourceProperty); |
| // Get the type of the property (to get or create their shapes) |
| var sourceType:UML::Type := sourceProperty.type; |
| var targetType:UML::Type := targetProperty.type; |
| |
| if(not sourceType.oclIsUndefined() and not targetType.oclIsUndefined()){ |
| |
| // Get the source and the target shapes if exists |
| var sourceShape:notation::Shape := parent.children[notation::Shape]->any(curr | not curr.element.oclIsUndefined() and curr.element.oclIsKindOf(UML::Type) and curr.element.oclAsType(UML::Type) = sourceType); |
| |
| var associationEdge := object notation::Connector{ |
| element := self.element; |
| |
| var isSourceCreated:Boolean := false; |
| if (sourceShape.oclIsUndefined()) { |
| sourceShape := createShape(parent, sourceType); |
| var createdBounds:notation::Bounds := object notation::Bounds{}; |
| if (self.layoutConstraint.oclIsKindOf(notation::Bounds)) { |
| createdBounds.x := self.layoutConstraint.oclAsType(notation::Bounds).x; |
| createdBounds.y := self.layoutConstraint.oclAsType(notation::Bounds).y; |
| createdBounds.width := self.layoutConstraint.oclAsType(notation::Bounds).width; |
| createdBounds.height := self.layoutConstraint.oclAsType(notation::Bounds).height; |
| }; |
| sourceShape.oclAsType(notation::Shape).layoutConstraint := createdBounds; |
| isSourceCreated := true; |
| parent.children += sourceShape; |
| }; |
| |
| var targetShape:notation::Shape := parent.children[notation::Shape]->any(curr | not curr.element.oclIsUndefined() and curr.element.oclIsKindOf(UML::Type) and curr.element.oclAsType(UML::Type) = targetType); |
| if (targetShape.oclIsUndefined()) { |
| targetShape := createShape(parent, targetType); |
| var createdBounds:notation::Bounds := object notation::Bounds{}; |
| if (self.layoutConstraint.oclIsKindOf(notation::Bounds)) { |
| // If the source and the target are created, move the target to 100 |
| var createdX:Integer := self.layoutConstraint.oclAsType(notation::Bounds).x; |
| if (isSourceCreated) { |
| createdX := createdX + 100; |
| }; |
| createdBounds.x := createdX; |
| createdBounds.y := self.layoutConstraint.oclAsType(notation::Bounds).y; |
| createdBounds.width := self.layoutConstraint.oclAsType(notation::Bounds).width; |
| createdBounds.height := self.layoutConstraint.oclAsType(notation::Bounds).height; |
| }; |
| targetShape.oclAsType(notation::Shape).layoutConstraint := createdBounds; |
| parent.children += targetShape; |
| }; |
| |
| source := sourceShape; |
| target := targetShape; |
| |
| }; |
| createBendpointsForAssociation(associationEdge); |
| createDefaultAssociationDecorationNodes(associationEdge); |
| rootDiagram.edges += associationEdge; |
| }; |
| |
| removeFromOwnerView(parent, self); |
| } |
| |
| mapping notation::Shape::fromSysML11AssociationClass(inout parent:notation::View) when {self.oclIsTypeOf(notation::Shape) and not self.element.oclIsUndefined() and self.element.oclIsKindOf(UML::AssociationClass)} { |
| |
| // Create the AssociationClass |
| var existingChildren:OrderedSet(notation::Node) := self.children; |
| var createdAssociationClassShape:notation::Shape := self; |
| createdAssociationClassShape.children := object OrderedSet(notation::Node){}; |
| modifyAssociationClassShape(createdAssociationClassShape, parent); |
| parent.children += createdAssociationClassShape; |
| |
| // Create the connector and the target and source if needed |
| var associationClass:UML::AssociationClass := self.element.oclAsType(UML::AssociationClass); |
| |
| var assocationProperty:UML::Property := associationClass.ownedEnd->any(true); |
| var association:UML::Association := assocationProperty.association; |
| |
| // Get the [0] and [1] member end for the source and target properties |
| var sourceProperty:UML::Property := association.memberEnd->any(true); |
| var targetProperty:UML::Property := association.memberEnd->any(curr | curr <> sourceProperty); |
| // Get the type of the property (to get or create their shapes) |
| var sourceType:UML::Type := sourceProperty.type; |
| var targetType:UML::Type := targetProperty.type; |
| |
| // Get the source and the target shapes if exists |
| var targetShape:notation::Shape := parent.children[notation::Shape]->any(curr | not curr.element.oclIsUndefined() and curr.element.oclIsKindOf(UML::Type) and curr.element.oclAsType(UML::Type) = targetType); |
| |
| var associationClassEdge := object notation::Connector{ |
| element := self.element; |
| |
| var isTargetCreated:Boolean := false; |
| if (targetShape.oclIsUndefined()) { |
| targetShape := createShape(parent, targetType); |
| var createdBounds:notation::Bounds := object notation::Bounds{}; |
| if (self.layoutConstraint.oclIsKindOf(notation::Bounds)) { |
| createdBounds.x := self.layoutConstraint.oclAsType(notation::Bounds).x; |
| createdBounds.y := self.layoutConstraint.oclAsType(notation::Bounds).y; |
| createdBounds.width := self.layoutConstraint.oclAsType(notation::Bounds).width; |
| createdBounds.height := self.layoutConstraint.oclAsType(notation::Bounds).height; |
| }; |
| targetShape.oclAsType(notation::Shape).layoutConstraint := createdBounds; |
| isTargetCreated := true; |
| parent.children += targetShape; |
| }; |
| |
| var sourceShape:notation::Shape := parent.children[notation::Shape]->any(curr | not curr.element.oclIsUndefined() and curr.element.oclIsKindOf(UML::Type) and curr.element.oclAsType(UML::Type) = sourceType); |
| if (sourceShape.oclIsUndefined()) { |
| sourceShape := createShape(parent, sourceType); |
| var createdBounds:notation::Bounds := object notation::Bounds{}; |
| if (self.layoutConstraint.oclIsKindOf(notation::Bounds)) { |
| createdBounds.x := self.layoutConstraint.oclAsType(notation::Bounds).x; |
| var createdY:Integer := self.layoutConstraint.oclAsType(notation::Bounds).y; |
| // If the source and the target are created, move the target to 200 |
| if (isTargetCreated) { |
| createdY := createdY + 200; |
| }; |
| createdBounds.y := createdY; |
| createdBounds.width := self.layoutConstraint.oclAsType(notation::Bounds).width; |
| createdBounds.height := self.layoutConstraint.oclAsType(notation::Bounds).height; |
| }; |
| sourceShape.oclAsType(notation::Shape).layoutConstraint := createdBounds; |
| parent.children += sourceShape; |
| }; |
| |
| source := sourceShape; |
| target := targetShape; |
| }; |
| createBendpointsForAssociation(associationClassEdge); |
| createDefaultAssociationClassDecorationNodes(associationClassEdge); |
| rootDiagram.edges += associationClassEdge; |
| |
| var associationClassTetherEdge := object notation::Connector{ |
| element := self.element; |
| type := ASSOCIATIONCLASS_TETHEREDGE_SYSML14; |
| |
| source := associationClassEdge; |
| target := createdAssociationClassShape; |
| |
| styles += object notation::FontStyle{}; |
| }; |
| createBendpointsForAssociationTetherEdge(associationClassTetherEdge); |
| rootDiagram.edges += associationClassTetherEdge; |
| } |
| |
| helper createShape(parent:notation::View, element:UML::NamedElement) : notation::Shape { |
| var res:notation::Shape; |
| if (element.oclIsKindOf(UML::Model)) { |
| res := createModelShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::Package)) { |
| res := createPackageShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::Component)) { |
| res := createComponentShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::Class)) { |
| res := createClassShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::Interface)) { |
| res := createInterfaceShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::InstanceSpecification)) { |
| res := createInstanceSpecificationShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::DataType)) { |
| res := createDataTypeShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::DurationObservation)) { |
| res := createDurationObservationShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::TimeObservation)) { |
| res := createTimeObservationShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::Enumeration)) { |
| res := createEnumerationShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::InformationItem)) { |
| res := createInformationItemShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::PrimitiveType)) { |
| res := createPrimitiveTypeShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::Signal)) { |
| res := createSignalShape(parent, element.oclAsType(ecore::EObject)); |
| } elif (element.oclIsKindOf(UML::Constraint)) { |
| res := createConstraintShape(parent, element.oclAsType(ecore::EObject)); |
| } else { |
| res := createNamedElementDefaultShape(element.oclAsType(ecore::EObject)); |
| }; |
| return res; |
| } |