blob: 84757443e9a7693cfa0667864422f587bd6d4ff2 [file] [log] [blame]
/*****************************************************************************
* 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 org.eclipse.papyrus.interoperability.rpy.blackboxes.sysml11.NestedConnectorEndBlackboxes;
import org.eclipse.papyrus.interoperability.rpy.blackboxes.Rpy2PapyrusNotationBlackboxes;
import org.eclipse.papyrus.interoperability.rpy.blackboxes.uml.UMLRpySemanticHelper;
import Rpy2PapyrusSemanticElements;
import RpyToPapyrus;
import RpyUtils;
import SysMLRpyUtils;
modeltype umlrpy "strict" uses 'http://www.eclipse.org/Papyrus/UMLRpy/1.0.0';
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' ;
/**
*
* WARNING : ISysMLPort is a part of Rpy metamodel and doesn't come from the SysML Rpy Profile
*
*
*/
transformation SysML11Profile(in inModel:umlrpy, out outModel:uml, in Sysml11Profile:sysml11, in primitives:UMLPrimitivesTypes)
extends Rpy2PapyrusSemanticElements(in inModel:umlrpy, out outModel:uml, in primitives:UMLPrimitivesTypes)
{
main() {
if (isRpySysMLProfileApplied() and sysml11<>null ) {
log("Start SysML Profiles and Stereotypes Application");
//if yes apply it to the output model
var model: Model := outModel.rootObjects()![uml::Model]->any(true);
// apply sysml 1.1 profile with all sub profiles
var sysml11Profiles : Set(Profile) := Sysml11Profile.objectsOfType(Profile);
sysml11Profiles->forEach(profile) {
model.applyProfile(profile);
};
//apply SysML 1.1 stereotype when it is applied in Rpy Model
inModel.objects()->select(rpy | not rpy.oclIsKindOf( GraphElementsType))->selectByKind(EObject).map applyRequiredSysML11Stereotype();
//apply NestedConnectorEnd stereotype
outModel.objects()->selectByKind(uml::ConnectorEnd).map applySysML11ConnectorEndStereotype();
log("End SysML Profiles and Stereotypes Application");
};
};
}
/**
* This mapping create the NestedConnectorEnd stereotype when required for the given object
*
*/
mapping uml::ConnectorEnd::applySysML11ConnectorEndStereotype() : sysml11::blocks::NestedConnectorEnd when {getNestedConnectorEndPropertyPath(self)->size()>0}{
base_ConnectorEnd:=self;
propertyPath:=getNestedConnectorEndPropertyPath(self);
}
/**
*
* Return true if the Rpy SysML Profile is applied on the Rpy model
*/
query isRpySysMLProfileApplied():Boolean {
var ret:Boolean = false;
var isProfiledModel:Boolean:=inModel.objectsOfType(IStereotype)->size()>0;
if (isProfiledModel) {
inModel.objectsOfType(IStereotype)->forEach(stereotype){
if(stereotype.isARpySysMLStereotype()){
ret:= true;
break;
}
}
};
return ret;
}
//--------------------------Here we are working on the Rpy Stereotypes--------------
/**
* This method manage the stereotype application from Rpy to Papyrus for a set of Rpy element
*
* TODO : edit the Rpy metamodel to get a common ancestor to manipulate easily the stereotyped element in Rpy
*/
mapping ecore::EObject::applyRequiredSysML11Stereotype() disjuncts
ecore::EObject::applyStereotypeFromIClass,
ecore::EObject::applyStereotypeFromIType_To_InstanceSpecification,
ecore::EObject::applyStereotypeFromIType_To_DataType,
ecore::EObject::applyStereotypeFromIType_To_Class,
ecore::EObject::applyStereotypeFromIType_To_Type,
ecore::EObject::applyStereotypeFromISysMLPort,
ecore::EObject::applyStereotypeFromIPart,
ecore::EObject::applyStereotypeFromIAttribute,
ecore::EObject::applyStereotypeFromIInformationFlow
{}
/**
* This method cross the stereotypes applied on the IClass and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIClass() when {self.oclIsTypeOf(IClass) /*and not self.oclAsType(IClass).Stereotypes->isEmpty()*/}{ //test on stereotype must be done in the method, because we always need to do some thing for IClass
var rpyElement:IClass:=self.oclAsType(IClass);
//we look for the created uml element
var umlElement:Element:=rpyElement.resolveoneIn(EObject::generalMappingToUMLElement, uml::Element);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
};
//apply Block and PropertySpecificType on some class
var nestedClassesForPart:Sequence(IClass):=rpyElement.Associations[IPart]->select(current | current.implicitClass<>null).implicitClass.oclAsSet();
nestedClassesForPart->forEach(current){
var umlClass:uml::Class:=current.resolveone().oclAsType(uml::Class);
umlClass.map applySysML11Stereotype(current.oclAsType(EObject), "Block");
umlClass.map applySysML11Stereotype(current.oclAsType(EObject), "PropertySpecificType");
};
}
/**
* This method cross the stereotypes applied on the IType and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIType_To_InstanceSpecification() when {self.oclIsTypeOf(IType) and not self.oclAsType(IType).Stereotypes->isEmpty() and self.resolveoneIn(EObject::iTypeToUMLInstanceSpecification, InstanceSpecification)<>null}{
var rpyElement:IType:=self.oclAsType(IType);
//we look for the created uml element
var umlElement:Element:=self.resolveoneIn(EObject::iTypeToUMLInstanceSpecification, InstanceSpecification);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
}
}
/**
* This method cross the stereotypes applied on the IType and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIType_To_DataType() when {self.oclIsTypeOf(IType) and not self.oclAsType(IType).Stereotypes->isEmpty() and self.resolveoneIn(EObject::iTypeToUMLDatatype, DataType)<>null}{
var rpyElement:IType:=self.oclAsType(IType);
//we look for the created uml element
var umlElement:Element:=self.resolveoneIn(EObject::iTypeToUMLDatatype, DataType);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
}
}
//TODO umlDataType and umlClass are probably useless now, waiting for JUnit tests to remove them from this method
/**
* This method cross the stereotypes applied on the IType and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIType_To_Class() when {self.oclIsTypeOf(IType) and not self.oclAsType(IType).Stereotypes->isEmpty() and self.resolveoneIn(EObject::iTypeToUMLClass, Class)<>null}{
var rpyElement:IType:=self.oclAsType(IType);
//we look for the created uml element
var umlElement:Element:=rpyElement.resolveoneIn(EObject::iTypeToUMLClass, Class);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
};
//in all case, we apply block on the class
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName("Block"));
}
}
/**
* This method cross the stereotypes applied on the IType and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIType_To_Type() when {self.oclIsTypeOf(IType) and not self.oclAsType(IType).Stereotypes->isEmpty() and self.resolveoneIn(EObject::generalMappingToUMLElement, Type)<>null}{
var rpyElement:IType:=self.oclAsType(IType);
//we look for the created uml element
var umlElement:Element:=self.resolveoneIn(EObject::generalMappingToUMLElement, Type);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
}
}
/**
* This method cross the stereotypes applied on the ISysMLPort and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromISysMLPort() when {self.oclIsTypeOf(ISysMLPort) and not self.oclAsType(ISysMLPort).Stereotypes->isEmpty()}{
var rpyElement:ISysMLPort:=self.oclAsType(ISysMLPort);
//we look for the created uml element
var umlElement:Element:=rpyElement.resolveoneIn(umlrpy::IRelation::iRelationToUMLElement);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
}
}
/**
* This method cross the stereotypes applied on the IPart and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIPart() when {self.oclIsTypeOf(IPart) and not self.oclAsType(IPart).Stereotypes->isEmpty()}{
var rpyElement:IPart:=self.oclAsType(IPart);
//we look for the created uml element
var umlElement:Element:=rpyElement.resolveoneIn(umlrpy::IPart::iPartToUMLElement);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
}
}
/**
* This method cross the stereotypes applied on the IAttribute and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIAttribute() when {self.oclIsTypeOf(IAttribute) and not self.oclAsType(IAttribute).Stereotypes->isEmpty()}{
var rpyElement:IAttribute:=self.oclAsType(IAttribute);
//we look for the created uml element
var umlElement:Element:=rpyElement.resolveoneIn(IVariable::iVariableToUMLElement, uml::Property);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
}
}
/**
* This method cross the stereotypes applied on the IInformationFlow and call the method to apply them on the equivalent uml element
*/
mapping ecore::EObject::applyStereotypeFromIInformationFlow() when {self.oclIsTypeOf(IInformationFlow) and not self.oclAsType(IInformationFlow).Stereotypes->isEmpty()}{
var rpyElement:IInformationFlow:=self.oclAsType(IInformationFlow);
//we look for the created uml element
var umlElement:Element:=rpyElement.resolveoneIn(umlrpy::IInformationFlow::iInformationFlowToUMLElement);
if(umlElement<>null){
rpyElement.Stereotypes->selectByType(umlrpy::IStereotype)->forEach(current){
umlElement.map applySysML11Stereotype(rpyElement.oclAsType(EObject), getSysML11StereotypeName(current.name));
}
}
}
//--------------------------Here we are working on the UML Stereotypes-------------------
/**
* Common method to apply a UML stereotype from the rpy element and from its name to a UML Element
*/
mapping uml::Element::applySysML11Stereotype(rpyElement:EObject, umlSteName:String):EObject disjuncts
uml::DataType::applySysML11ValueType,
uml::InstanceSpecification::applySysML11Dimension,
uml::InstanceSpecification::applySysML11Unit,
uml::Class::applySysML11Block,
uml::Property::applySysML11FlowProperty,
uml::Port::applySysML11FlowPort,
//default mapping method
uml::Element::applySysML11Stereotype_DefaultMapping
{}
/**
* Default mapping to apply Sysml11 stereotype
*
*/
mapping uml::Element::applySysML11Stereotype_DefaultMapping(rpyElement:EObject, umlSteName:String):EObject when {getSysML11Stereotype(umlSteName)<>null}{
init {
var stereotypeToApply:Stereotype:=getSysML11Stereotype(umlSteName);
self.applyStereotype(stereotypeToApply);
result:=self.getAppliedStereotype(stereotypeToApply.getQualifiedName()).oclAsType(EObject);
}
}
/**
*
* This method apply the stereotype SysML FlowPort
*/
mapping uml::Port::applySysML11FlowPort(rpyElement:EObject, stereotypeName:String):EObject when{rpyElement.oclIsKindOf(ISysMLPort) and stereotypeName="FlowPort"}{
init{
var stereotypeApplication:sysml11::portandflows::FlowPort:= object sysml11::portandflows::FlowPort{
base_Port:=self;
direction:=getSysML11FlowDirection(rpyElement.oclAsType(ISysMLPort).direction);
if(not self.isAtomic(rpyElement.oclAsType(umlrpy::ISysMLPort))){
//If the FlowPort is atomic (by its type), then isAtomic=True, the direction must be specified (has a value), and
//isConjugated is not specified (has no value).
isConjugated:=rpyElement.oclAsType(ISysMLPort).isConjugated();
}else{
isConjugated:=false;
};
};
result:=stereotypeApplication.oclAsType(EObject);
}
}
/**
* @param a ISysMLPort
*
* @return true if the port is atomic and false otherwise
*
*/
helper uml::Port::isAtomic(rpyPort:umlrpy::ISysMLPort): Boolean{
var isAtomic:Boolean:=true;
if(self.type<>null){
//1. we need to call the mapping for stereotype applied on the type of the port to know if it is stereotyped with FlowSpecification
rpyPort.oclAsType(ISysMLPort).otherClass.oclAsType(EObject).map applyRequiredSysML11Stereotype();
//2. now we could check the stereotype applied on the type of the port
var flowSpec:uml::Stereotype:=self.type.getAppliedStereotype(getSysML11Stereotype("FlowSpecification").getQualifiedName());
if (flowSpec<> null) {
isAtomic:=false;
};
};
return isAtomic;
}
/**
*
* This method apply the stereotype SysML FlowPort
*/
mapping uml::Property::applySysML11FlowProperty(rpyElement:EObject, stereotypeName:String):EObject when{rpyElement.oclIsKindOf(IAttribute) and stereotypeName="FlowProperty"}{
init{
var stereotypeApplication:sysml11::portandflows::FlowProperty:= object sysml11::portandflows::FlowProperty{
base_Property:=self;
//we have model with 2 kind of declaration for the same thing...
//the first way!
var dir:String:=rpyElement.oclAsType(IAttribute).Tags->any(name="direction" and typeOf.oclAsType(IType).name="FlowDirection").ValueSpecifications->any(true).oclAsType(ILiteralSpecification).value;
//the 2nd way is required
if(dir.oclIsUndefined()){
//probably due to an error in the model, but in soem case we met RhpString
dir:=rpyElement.oclAsType(IAttribute).Tags->any(name="direction" and typeOf.oclAsType(IType).name="RhpString").ValueSpecifications->any(true).oclAsType(ILiteralSpecification).value;
};
direction:=getSysML11FlowDirection(dir);
};
result:=stereotypeApplication.oclAsType(EObject);
}
}
/**
* This method apply the stereotype Block
*/
mapping uml::Class::applySysML11Block(rpyElement:EObject, stereotypeName:String):EObject when{stereotypeName="Block"}{
init{
var stereotypeApplication:sysml11::blocks::Block:= object sysml11::blocks::Block{
base_Class:=self;
};
result:=stereotypeApplication.oclAsType(EObject);
}
}
/**
* This method apply the stereotype Dimension
*/
mapping uml::InstanceSpecification::applySysML11Dimension(rpyElement:EObject, umlSteName:String):EObject when {umlSteName="Dimension"}{
init{
var stereotypeApplication:sysml11::blocks::Dimension:= object sysml11::blocks::Dimension{
base_InstanceSpecification:=self;
};
result:=stereotypeApplication.oclAsType(EObject);
}
}
/**
* This method apply the stereotype Unit
*/
mapping uml::InstanceSpecification::applySysML11Unit(rpyElement:EObject, umlSteName:String):EObject when {umlSteName="Unit" and rpyElement.oclIsKindOf(IType)}{
init{
var stereotypeApplication:sysml11::blocks::Unit:= object sysml11::blocks::Unit{
base_InstanceSpecification:=self;
//manage the dimension field
var tt:umlrpy::ITag=rpyElement.oclAsType(IType).Tags->select(t | t.name="dimension")->any(true);
var iinstancespec:umlrpy::IInstanceValue=tt.ValueSpecifications->selectByKind(umlrpy::IInstanceValue)->any(true);
if(iinstancespec<>null){
var val = iinstancespec.value;
var res:uml::InstanceSpecification = val.resolveoneIn(EObject::iTypeToUMLInstanceSpecification);
dimension:=res.map applySysML11Stereotype(val.oclAsType(EObject),"Dimension").oclAsType(sysml11::blocks::Dimension);
}
};
result:=stereotypeApplication.oclAsType(EObject);
}
}
mapping uml::DataType::applySysML11ValueType(rpyElement:EObject, umlSteName:String):EObject when {umlSteName="ValueType" and rpyElement.oclIsKindOf(IType)}{
init{
var stereotypeApplication:sysml11::blocks::ValueType:= object sysml11::blocks::ValueType{
base_DataType:=self;
//manage the dimension field
var dimensionTag:umlrpy::ITag=rpyElement.oclAsType(IType).Tags->select(t | t.name="dimension")->any(true);
var dimensionInstanceIInstancespec:umlrpy::IInstanceValue=dimensionTag.ValueSpecifications -> selectByKind(umlrpy::IInstanceValue)->any(true);
if(dimensionInstanceIInstancespec<>null){
var val = dimensionInstanceIInstancespec.value;
var res:uml::InstanceSpecification = val.resolveoneIn(EObject::iTypeToUMLInstanceSpecification);
dimension:=res.map applySysML11Stereotype(val.oclAsType(EObject),"Dimension").oclAsType(sysml11::blocks::Dimension);
};
//manage the unit field
var unitTag:umlrpy::ITag=rpyElement.oclAsType(IType).Tags->select(t | t.name="unit")->any(true);
var unitInstanceIInstancespec:umlrpy::IInstanceValue=unitTag.ValueSpecifications -> selectByKind(umlrpy::IInstanceValue)->any(true);
if(unitInstanceIInstancespec<>null){
var val = unitInstanceIInstancespec.value;
var res:uml::InstanceSpecification = val.resolveoneIn(EObject::iTypeToUMLInstanceSpecification);
unit:=res.map applySysML11Stereotype(val.oclAsType(EObject),"Unit").oclAsType(sysml11::blocks::Unit);
};
};
result:=stereotypeApplication.oclAsType(EObject);
}
}
/**
*
* Return the SysML 1.1 Stereotype for the given string or null if not found
*/
query getSysML11Stereotype(rpyStereotypeName:String ) :uml::Stereotype {
return Sysml11Profile.objectsOfType(Stereotype)![name=getSysML11StereotypeName(rpyStereotypeName)];
}
/**
* Return the SysML 1.1 name corresponding to the Rpy SysML Name
*/
query getSysML11StereotypeName(rpyStereotypeName:String): String{
var sysml11SteName:=switch{
case (rpyStereotypeName="flowSpecification") "FlowSpecification";
case (rpyStereotypeName="flowProperty") "FlowProperty";
case (rpyStereotypeName="flowPort") "FlowPort";
case (rpyStereotypeName="block") "Block";
//all case where the Rpy SysML Stereotype name is the same than the Papyrus SysML Name
case (true) rpyStereotypeName;
};
return sysml11SteName
}
/**
*
* This method convert the rhaspody flow direction into the SysML FlowDirection
*/
query getSysML11FlowDirection(rpyDirection:String) : sysml11::portandflows::FlowDirection{
var direction: sysml11::portandflows::FlowDirection;
direction:= switch {
case (rpyDirection="In") sysml11::portandflows::FlowDirection::_in;
case (rpyDirection="Out") sysml11::portandflows::FlowDirection::_out;
case (rpyDirection="InOut") sysml11::portandflows::FlowDirection::_inout;
case (rpyDirection="Bidirectional") sysml11::portandflows::FlowDirection::_inout;
case (true) sysml11::portandflows::FlowDirection::_inout;
};
return direction;
}