blob: 29283ce88f2852d304ea6b78e4f147d4c3689584 [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.uml.AssociationOwnerHelper;
import org.eclipse.papyrus.interoperability.common.blackboxes.uml.UMLHelper;
import RpyToPapyrusUtils;
import SysMLRpyUtils;
import RpyUtils;
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 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 UMLPrimitivesTypes "strict" uses 'http://www.eclipse.org/uml2/5.0.0/Types' ;
//add syml profile
modeltype sysml11 "strict" uses 'http://www.eclipse.org/papyrus/0.7.0/SysML';
/**
* Transformation rules for importing a Rpy Semantic model into a UML model
*/
transformation Rpy2PapyrusSemanticElements(in inModel:umlrpy, out outModel:uml, in primitives:UMLPrimitivesTypes);
property events : Set(IEvent) = null;
/**This variable is used to reference the types created outside of all contexts. (bug 510869)*/
property userTypeDeclaration: Set(Type);
/**The UML Package representing the Rpy libraries and user custom types*/
property typesLibraries:Sequence(uml::Package);
/**
* Maunch the semantic transformation
*/
main() {
log('Start UML Semantic QVTo Transfo');
inModel.rootObjects()[IProject]->map iProjectToPapyrusModel();
setAssociationOwnerAndClear();
log('Finish UML Semantic QVTO Transfo');
};
/**
*
* Create a Model from the IProject
*/
mapping umlrpy::IProject::iProjectToPapyrusModel() : uml::Model {
name:=self.name.replaceAll("\"","");
eAnnotations+=inModel.rootObjects()->selectByType(IProject)![IProject].createEAnnotationForVersioning();
var localComment:Comment:=self.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
//we map the packaged elements
packagedElement+=self.Subsystems.map iDefaultSubsystemTypeToPackage();
//import uml basic primitives Types by default
var importedPackages: Set(PackageImport);
var models : Set(Model) := primitives.objectsOfType(Model);
models->forEach(package){
var packageImport:=object PackageImport{
importedPackage:=package;
};
importedPackages+=packageImport;
};
packageImport+=importedPackages;
if(userTypeDeclaration->notEmpty()){
typesLibraries+= object Package{
name:="UserTypesDeclaration";
packagedElement+=userTypeDeclaration;
}
};
//we sort the library by alphabetical order
var sortedLibrary:Sequence(uml::Package):=sortNamedElement(typesLibraries)->selectByKind(uml::Package);
sortedLibrary->forEach(pack){
//we sort the contents of the library by alphabetical order
var packageableElements:Sequence(PackageableElement):=pack.packagedElement->selectByKind(uml::PackageableElement)->asSequence();
pack.packagedElement:=null;
sortNamedElement(packageableElements)->forEach(n){
//we don't found an other way than this forEach to maintain the sort'
if(n.oclIsKindOf(uml::PackageableElement)){
pack.packagedElement+=n.oclAsType(uml::PackageableElement);
};
};
};
//we add them to the final model
packagedElement+=sortedLibrary;
}
/**
* Create packages from DefaultSubsystemType
*/
mapping umlrpy::DefaultSubsystemType::iDefaultSubsystemTypeToPackage():uml::Package when{self.oclIsKindOf(ISubsystem)}{
var iSubSystem:ISubsystem:=self.oclAsType(ISubsystem);
name:=iSubSystem.name;
//no idea about this code coming from the initial prototype
if(iSubSystem.SignalEvents()[IEvent].oclAsSet()->notEmpty()){
var SignalsPackage := object Package{
name:= "Signals";
packagedElement:= iSubSystem.SignalEvents()->selectByKind(EObject).map generalMappingToUMLElement().oclAsType(PackageableElement);
};
nestedPackage+=SignalsPackage;
};
//no idea about this code coming from the initial prototype
if(iSubSystem.SignalEvents()[IEvent].oclAsSet()->notEmpty()){
var SignalEventPackage := object Package{
name:= "Signal Events";
packagedElement:= iSubSystem.SignalEvents()[IEvent].map toSignalEvents();
};
nestedPackage+=SignalEventPackage;
};
packagedElement+=iSubSystem.Events->selectByType(IEvent)->selectByKind(EObject).map generalMappingToUMLElement().oclAsType(PackageableElement);
packagedElement+= iSubSystem.Classes->selectByType(IClass)->any(name="TopLevel").Attrs->selectByKind(IAttribute).oclAsType(EObject).map generalMappingToUMLElement().oclAsType(PackageableElement);
//TODO probably more check are required to remove TopLevel without problems (check with MARTE...)
packagedElement+= iSubSystem.Classes->selectByType(IClass)->select(curr | curr.name<>"TopLevel")->selectByKind(EObject).map generalMappingToUMLElement().oclAsType(uml::PackageableElement);
//managing rpy objects IAssociationClass
packagedElement+=iSubSystem.AssociationElements->selectByType(IAssociationClass)->selectByKind(EObject).map generalMappingToUMLElement().oclAsType(uml::PackageableElement);
packagedElement += iSubSystem.Types->selectByType(IType)->selectByKind(EObject).map generalMappingToUMLElement().oclAsType(uml::PackageableElement);
packagedElement += iSubSystem.Actors->selectByKind(IActor)->oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::PackageableElement);
packagedElement +=iSubSystem.Declaratives[DefaultSubsystemType].oclAsSet().map iDefaultSubsystemTypeToPackage();
ownedComment += iSubSystem.Annotations->select(a | (a.oclIsTypeOf(IAnnotation) or a.oclIsTypeOf(IComment)))->oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
var localComment:Comment:=iSubSystem.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
*
* This method has been created to be the common entry point for all the semantic transformations from the Rpy Model to the UML Model
* TODO : rewrite all transformations in order to use me everywhere
*/
mapping ecore::EObject::generalMappingToUMLElement():uml::Element disjuncts
ecore::EObject::iActorToUMLActor,
ecore::EObject::iCommentToUMLComment,
ecore::EObject::iDescriptionToUMLComment,
ecore::EObject::iAttributeToUMLInstanceSpecification,
ecore::EObject::iClassToUMLInterface,
ecore::EObject::iClassToUMLClass,
ecore::EObject::iEventToUMLSignal,
ecore::EObject::iTypeToUMLDatatype,
ecore::EObject::iTypeToUMLInstanceSpecification,
ecore::EObject::iTypeToUMLEnumeration,
ecore::EObject::iTypeToUMLClass, //TODO : merge me with the existing other way to create a class
ecore::EObject::iTypeToDefault,
ecore::EObject::iAssociationClassToUMLAssociation
{}
/**
* This mapping convert an IActor into a UML Actor
*/
mapping EObject::iActorToUMLActor():uml::Actor when {self.oclIsTypeOf(umlrpy::IActor)}{
var actor:IActor:=self.oclAsType(IActor);
name:=actor.name;
ownedComment += actor.Annotations->selectByType(IComment).oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
var localComment:Comment:=actor.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
*
* This mapping convert a IComment into a UML Comment
*/
mapping EObject::iCommentToUMLComment(): uml::Comment when {self.oclIsTypeOf(IComment)}{
var comment:IComment:=self.oclAsType(IComment);
body:=comment.body;
if(body=null or body.size()=0){
body:=comment.description.text;
if(body=null or body.size()=0){
body:=comment.description.textRTF.getTextWithoutMarkers();
}
};
comment.Anchors->forEach(anchor){
var rpyAnnotatedElement:EObject:=anchor.dependsOn.oclAsType(EObject);
//this is the generic method to call to create/find mapped element
var resolvedContext:Element:=rpyAnnotatedElement.map generalMappingToUMLElement();
//TODO : the code of the transformation should be refactored to use the previous one, nevertheless, waiting for this refactoring, we use this code
if(resolvedContext=null){
var metaClassName:String:= rpyAnnotatedElement.metaClassName();
annotatedElement+=switch{
case (metaClassName="IPart") rpyAnnotatedElement.oclAsType(umlrpy::IPart).map iPartToUMLElement().oclAsType(uml::Element);
case (metaClassName="IAttribute") rpyAnnotatedElement.oclAsType(umlrpy::IAttribute).map iVariableToUMLElement().oclAsType(uml::Element);
};
}else{
annotatedElement+=resolvedContext;
}
}
}
/**
*
* This mapping convert a IDescription into a UML Comment
*/
mapping EObject::iDescriptionToUMLComment(): uml::Comment when {self.oclIsTypeOf(IDescription)}{
var description:IDescription:=self.oclAsType(IDescription);
body:=description.text;
if(body=null or body.size()=0){
body:=description.textRTF.getTextWithoutMarkers();
};
if(self.eContainer().oclIsKindOf(Element)){
annotatedElement+=self.eContainer().oclAsType(Element);
}
}
/**
* This method remove all markers in the string
*/
helper String::getTextWithoutMarkers():String{
//this code seems me quite specific to my examples, but I don't have better idea
// var res:String:=self.replaceAll("\\\\[a-zA-Z0-9]*", ""); //to remove all formatting information
//this regex works fine (for php, tested on https://regex101.com/r/9FfA4S/4))
// {\\\\[a-zA-Z0-9\\\\\s]*(;\}+)?|\\\\[a-zA-Z0-9]*
//a nicer regex
var res:String:=self.replaceAll("\\\\ldblquote\\s", "“"); //replace left quote followed by a space
res:=res.replaceAll("\\\\rdblquote\\s?","”"); //replace right quote maybe followed by a space
res:=res.replaceAll("\\\\pard",""); //remove explicitely the tag \\pard
res:=res.replaceAll("\\\\par","\n"); //replace all new paragraph by new line
res:=res.replaceAll("\\\\line","\n"); //replace all new paragraph by new line
res:=res.replaceAll("\\{\\\\[a-zA-Z0-9\\\\\\s]*(;\\}+)?|\\\\[a-zA-Z0-9]*\\s?", ""); //to remove all others formatting informations
res:=res.replaceAll("'\\w+(;})?",""); //in some case we get this kind of string after the first regex : 'cb'ce'cc'e5;}myText
res:=res.replaceAll("\r\n","\n");
var a:="}\n";
var lastIndex:=res.lastIndexOf(a);
if(lastIndex<>-1 and lastIndex=res.length()-(a.size()-1)){
res:=res.substring(1,lastIndex-1);
};
while(res.startsWith("\n") or res.startsWith("}") or res.startsWith(";") or res.startsWith("{")){
res:=res.substring(2,res.length());
};
while(res.endsWith("\n") or res.endsWith("}") or res.endsWith(";") or res.endsWith("{")){
res:=res.substring(1,res.length()-1);
};
return res;
}
/**
*
* return true if the IClass is representing an interface
*/
mapping ecore::EObject::iClassToUMLInterface() : uml::Interface when {self.oclIsTypeOf(umlrpy::IClass) and self.oclAsType(umlrpy::IClass).isInterface() /*self.isSysMLFlowSpecification()*/}{
var localIClass:umlrpy::IClass:=self.oclAsType(umlrpy::IClass);
name:= localIClass.name.replaceAll("\"","");
ownedAttribute+= localIClass.Attrs[IAttribute].map iVariableToUMLElement();
// ownedAttribute+= self.Associations[IAssociationEnd].map toAssociationsEnd();
// ownedOperation := self.Operations [IPrimitiveOperation].map toOperations();
// ownedReception:= self.Operations[IReception].map toReceptions();
// generalization:= self.Inheritances [IGeneralization].map toPapyrusGeneralization();
var localComment:Comment:=localIClass.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
*
* When we match any condition, we create a uml::DataType or a uml::Enumeration.
* We can be here in case of bug, when an existing type has not been resolved
* or when the user use the C type declaration in Rpy (declaring a type with a string, see bug 510869)
*/
mapping ecore::EObject::iTypeToDefault():uml::DataType when{self.oclIsTypeOf(IType)}{
init{
var localIType:IType:=self.oclAsType(IType);
var nameToUse:String:="";
if(localIType.name=null or localIType.name.oclIsInvalid()){
if(localIType.declaration<>null){
nameToUse:=localIType.declaration;
}
}else{
nameToUse:=localIType.name.replaceAll("\"","");
};
if(nameToUse.indexOf("Enum")=0){
result:=object DataType{};
}else{
result:=object Enumeration{};
}
}
name:=nameToUse;
var fileName:String:=localIType.oclAsType(EModelElement).getFileNameWithoutExtension();
var package:uml::Package:=fileName.map createPackageLibrary();
if(not package.oclIsUndefined()){
package.packagedElement+=result;
}
}
/**
* This mapping allows to create a package from a string
*/
mapping String::createPackageLibrary():uml::Package when {not self.oclIsUndefined()}{
name:=self;
typesLibraries+=result;
}
/**
* This method allows to map a RpyType on an other type
*/
query umlrpy::IType::mapToBasicType(inout templateableElement:TemplateableElement){
//we assurme here that the UML PrimitiveTypes are already imported
var baseType:IUnit := self.typedefBaseType;
if(not(baseType.oclIsUndefined()) and baseType.oclIsTypeOf(IType)){
// var name:String:=baseType.metaClassName();
var umlType:uml::Type :=baseType.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
if(not(umlType.oclIsUndefined())){//should never appends
var templateBinding := object uml::TemplateBinding{
};
// var redefinableTemplateSignature:=object uml::RedefinableTemplateSignature {
//
// };
var templateParameterSubstitution:= object TemplateParameterSubstitution{
};
// var classifierTemplateParameter:= object ClassifierTemplateParameter{
//
// };
templateableElement.templateBinding+=templateBinding;
templateBinding.boundElement:=templateableElement;
// //templateBinding.source:=templatableElement; //read only
// //templateBinding.target:=templateParameterSubstitution; //read only
// templateBinding.signature:=redefinableTemplateSignature;
templateBinding.parameterSubstitution+=templateParameterSubstitution;
templateParameterSubstitution.actual:=umlType;
};
};
// return templateableElement;
}
/**
* Return true if the object must be converted into a UML DataType
*
* For JUnit SysML test1:
* must be converted into UML Datatype :
* MyBool : kind = Typedef and stereotype = DataType
* MyArrayOfInt : kind = Typedef and stereotype DataType
* MyPrimitivesTypes : kind = Language and stereotype = DataType
* MySpeed : kind = kind = Typedef and ValueType
* IType defined in Rpy Library (like PredefinedTypes) must be imported as DatType
*/
query umlrpy::IType::isUMLDataType(): Boolean {
var res:=self.isSysMLValueType() and not self.isKindEnumeration();
if(not res){
res:=(self.isRpyDataType() or self.isRpyLibraryType()) and (self.isKindLanguage() or self.isKindTypedef());
};
return res;
}
/**
* Return true if the IType is kind Typedef
*/
query umlrpy::IType::isKindTypedef(): Boolean{
return self.kind="Typedef";
}
/**
* Return true if the IType is kind Enumeration
*/
query umlrpy::IType::isKindEnumeration(): Boolean{
return self.kind="Enumeration";
}
/**
* Return true if the IType is kind Enumeration
*/
query umlrpy::IType::isKindStructure(): Boolean{
return self.kind="Structure";
}
/**
* Return true if the IType has kind Language
*/
query umlrpy::IType::isKindLanguage(): Boolean {
return self.kind="Language";
}
query umlrpy::IType::isUMLClass(): Boolean{
return self.isKindStructure() and (self.isRpyDataType() or self.isSysMLValueType());
}
query umlrpy::IType::isUMLEnumeration():Boolean{
return self.isKindEnumeration() and ((self.isRpyDataType() or self.isSysMLValueType()) //TODO to check : is it required to check isDatatYpe and isSysmlValueType ?
or self.isRpyLibraryType()); //to create Enumeration for Type defined ni RpyLibrary
}
query umlrpy::IType::isUMLInstanceSpecification(): Boolean {
return self.isKindLanguage() and (self.isSysMLDimension() or self.isSysMLUnit());
}
//--------association code--------------
/**
* This mapping creates a UML association with its 2 members ends and owned ends when required, according to the navigability value
*/
mapping ecore::EObject::iAssociationClassToUMLAssociation(): uml::Association when{self.oclIsKindOf(IAssociationClass)}{
var localIAssociationClass:IAssociationClass:=self.oclAsType(IAssociationClass);
name:= localIAssociationClass.name.replaceAll("\"","");
var end1:IAssociationEnd:=localIAssociationClass.m_end1;
var end2:IAssociationEnd:=localIAssociationClass.m_end2;
var mapping1:Property:=end1.map toAssociationsEnd().oclAsType(Property);
var mapping2:Property:=end2.map toAssociationsEnd().oclAsType(Property);
//if navigable: owned by class
//if non navigable, owned by the association
memberEnd+=mapping1;
memberEnd+=mapping2;
if(not end1.isNavigable()){
ownedEnd+=mapping1;
};
if(not end2.isNavigable()){
ownedEnd+=mapping2;
}
}
/**
* Return true if the association end is navigable. In this case, the property will be owned by the class,
* otherwse, by the association
*/
helper umlrpy::IAssociationEnd::isNavigable():Boolean{
return self.navigability.equalsIgnoreCase("Navigable");
}
/**
* Common method to create association from an IAssociationEnd
*/
mapping umlrpy::IAssociationEnd::iAssociationEndToUMLAssociation(): uml::Association disjuncts
umlrpy::IAssociationEnd::iAssociationEndToUMLAssociation_case1,
umlrpy::IAssociationEnd::iAssociationEndToUMLAssociation_case2
{}
mapping umlrpy::IAssociationEnd::iAssociationEndToUMLAssociation_case1(): uml::Association when {self.isNavigable() and self.inverse.oclIsUndefined()}{
//please keep this order (O source and 1 target) -> if we change this property we broke the BDD of test2
//when isNavigable() returns true, the property is owned by the classifier
//when isNavigable() returns false, the property is owned by the association
//here, in the Rpy model, we have only one end, so here this end will be owned by the classifier and the other one by the association
var localMemberEnd:=self.map toAssociationsEnd();
memberEnd+= localMemberEnd;
var localOwnedEnd:= object Property{
type:= self.container().oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
};
ownedEnd+= localOwnedEnd;
name:=localOwnedEnd.type.name + " refers to " + localMemberEnd.type.name + " as " + localMemberEnd.name;
}
mapping umlrpy::IAssociationEnd::iAssociationEndToUMLAssociation_case2():uml::Association when{
self.isNavigable() and
(not self.inverse.oclIsUndefined())
and self.inverse.oclIsTypeOf(IAssociationEnd)
and self.inverse.oclAsType(IAssociationEnd).isNavigable()
and self.m_associationClass.oclIsUndefined()}{ //in this case, the association is created by the mapping for IAssociationClass
//when isNavigable() returns true, the property is owned by the classifier
//when isNavigable() returns false, the property is owned by the association
//-> here the 2 properties are owned by the classifier
init{
//this resolve is not a mistake. We call resolve to avoid to create several time the same association
result:=self.inverse.resolveoneIn(umlrpy::IAssociationEnd::iAssociationEndToUMLAssociation_case2);
}
if(result.memberEnd->size()=0){//the result has been created goint out of the init, because the resolve doesn't allow to find an existing association
result.memberEnd+=self.map toAssociationsEnd();
result.memberEnd+=self.inverse.oclAsType(IAssociationEnd).map toAssociationsEnd();
//order of member can't be determined in this case
}
}
mapping umlrpy::IAssociationEnd::toAssociationsEnd(): uml::Property when{self.oclIsTypeOf(IAssociationEnd)}{
name:=self.name.replaceAll("\"","");
type:= self.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
aggregation:=AggregationKind::none;
}
/**
*
* This mapping convert a IPart into a uml Element
*/
mapping umlrpy::IPart::iPartToUMLElement():uml::Element disjuncts
umlrpy::IPart::iPartToUMLProperty
{}
/**
* This method convert an IPart into a uml Property
*
*/
mapping umlrpy::IPart::iPartToUMLProperty():uml::Property when {self.oclIsTypeOf(IPart)}{
name:= self.name.replaceAll("\"","");
//TODO : manage aggregation kind
aggregation:=AggregationKind::composite;
type:=self.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Type);
if((not self.multiplicity.oclIsUndefined()) and self.multiplicity<>"1"){
lowerValue:=createLowerMultiplicity(self.multiplicity);
upperValue:=createUpperMultiplicity(self.multiplicity);
};
var localComment:Comment:=self.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
mapping umlrpy::IPart::iPartToUMLAssociation():uml::Association when {true}{
var part:uml::Property:=self.resolveoneIn(umlrpy::IPart::iPartToUMLProperty); //TODO : replace me with a mapping
var propOwner:uml::NamedElement:=part.owner.oclAsType(NamedElement);
var propType:=part.type;
var initialVal:=propType.invresolveone();//TODO is it a good idea to use unresolve ?
var res:Boolean:=false;
if(initialVal.oclIsTypeOf(umlrpy::IClass)){
//TODO : make a util for this stereotype application
res:=initialVal.oclAsType(umlrpy::IClass).Stereotypes[IStereotype]->select(ste | ste.name="ConstraintBlock")->notEmpty();
};
if(res){
name:=propOwner.name + " has constraint " + propType.name + " applied as " + part.name;
}elif(part.aggregation.toString()=AggregationKind::composite.toString()){
name:=propOwner.name + " owns a " + propType.name + " as " + part.name;
};
var ownedEnd2:uml::Property:= object Property{};
ownedEnd2.name:=propOwner.name.toLowerCase();
ownedEnd2.type:=propOwner.oclAsType(uml::Type);
memberEnd+=ownedEnd;
memberEnd+=part;
ownedEnd+=ownedEnd2;
}
//------end of association code----------------------
mapping ecore::EObject::iTypeToUMLDatatype() : uml::DataType when {self.oclIsTypeOf(IType) and self.oclAsType(IType).isUMLDataType()}{
var localIType:IType:=self.oclAsType(IType);
name:= localIType.name.replaceAll("\"","");
ownedAttribute+=localIType.Attrs[IAttribute].map iVariableToUMLElement();
localIType.mapToBasicType(result.oclAsType(uml::TemplateableElement));
if(not localIType.isRpyLibraryType()){
var localComment:Comment:=localIType.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
};
}
mapping ecore::EObject::iTypeToUMLEnumeration() : uml::Enumeration when {self.oclIsTypeOf(IType) and self.oclAsType(IType).isUMLEnumeration()}{
var localIType:IType:=self.oclAsType(IType);
name:= localIType.name.replaceAll("\"","");
ownedLiteral+=localIType.Literals[IEnumerationLiteral].map toUMLEnumerationLiteral();
localIType.mapToBasicType(result.oclAsType(uml::TemplateableElement));
if(not localIType.isRpyLibraryType()){
var localComment:Comment:=localIType.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
};
}
mapping umlrpy::IEnumerationLiteral::toUMLEnumerationLiteral() : uml::EnumerationLiteral {
name:= self.name.replaceAll("\"","");
if(not self.oclAsType(EObject).isRpyLibraryType()){
var localComment:Comment:=self.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
};
}
mapping ecore::EObject::iTypeToUMLInstanceSpecification() : uml::InstanceSpecification when {self.oclIsTypeOf(IType) and self.oclAsType(IType).isUMLInstanceSpecification()}{
var localIType:IType:=self.oclAsType(IType);
name:= localIType.name.replaceAll("\"","");
var localComment:Comment:=localIType.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
//TODO : refactore me, there is at least 2 method to create a class, on efrom an IType and an other one from a IClass
mapping ecore::EObject::iTypeToUMLClass() : uml::Class when {self.oclIsTypeOf(IType) and self.oclAsType(IType).isUMLClass()}{//stereotype Block is added later in the process
var localIType:IType:=self.oclAsType(IType);
name:= localIType.name.replaceAll("\"","");
ownedAttribute+=localIType.Attrs[IAttribute].map iVariableToUMLElement();
localIType.mapToBasicType(result.oclAsType(uml::TemplateableElement));
var localComment:Comment:=localIType.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
mapping ecore::EObject::iClassToUMLClass(): uml::Class when {self.oclIsTypeOf(umlrpy::IClass) and not (self.oclAsType(umlrpy::IClass).isInterface())}{
var localIClass:umlrpy::IClass:=self.oclAsType(umlrpy::IClass);
name:= localIClass.name.replaceAll("\"","");
ownedAttribute+= localIClass.Attrs[IAttribute].map iVariableToUMLElement();
ownedAttribute+= localIClass.Associations[IPart].map iPartToUMLElement().oclAsType(uml::Property);
var associationsToAdd:=localIClass.Associations[IPart].map iPartToUMLAssociation();
nestedClassifier+= localIClass.Associations[IPart]->select(current | current.implicitClass<>null).implicitClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Classifier);
nestedClassifier+=localIClass.Declaratives->selectByType(IClass)->selectByKind(EObject).map generalMappingToUMLElement().oclAsType(uml::Classifier);
ownedAttribute+= localIClass.Associations->selectByType(IAssociationEnd)->select(a | a.isNavigable()).map toAssociationsEnd();
associationsToAdd+=localIClass.Associations[IAssociationEnd].map iAssociationEndToUMLAssociation();
ownedOperation += localIClass.Operations [IPrimitiveOperation].map toOperations();
ownedReception += localIClass.Operations[IReception].map toReceptions();
generalization += localIClass.Inheritances [IGeneralization].map toPapyrusGeneralization();
ownedBehavior += localIClass.StateCharts[IStateChart].map toStateMachine();
ownedAttribute+=localIClass.Ports.map iRelationToUMLElement().oclAsType(uml::Property);
ownedConnector+=localIClass.ObjectLinks[IObjectLink].map iObjectLinkToUMLElement().oclAsType(uml::Connector);
ownedConnector+=localIClass.Declaratives[IInformationFlow].map iInformationFlowToUMLElement().oclAsType(uml::Connector);
ownedComment+=localIClass.Annotations.oclAsType(IComment).oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
registerAssociationToStore(result, associationsToAdd);
var localComment:Comment:=localIClass.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
* This method map a IObjectLink with a UML Element
*
*/
mapping umlrpy::IInformationFlow::iInformationFlowToUMLElement():uml::Element disjuncts
umlrpy::IInformationFlow::iInformationFlowToUMLConnector
{}
/**
* This method map a IInformationFlow with a UML Connector
*
*/
mapping umlrpy::IInformationFlow::iInformationFlowToUMLConnector():uml::Connector when{self.isUMLConnector() }{
name:= self.name.replaceAll("\"","");
_end+=self.map iInformationFlowSourceToUMLConnectorEnd();
_end+=self.map iInformationFlowTargetToUMLConnectorEnd();
}
/**
* This method map a IInformationFlow with a UML Connector End used as source
*
*/
mapping umlrpy::IInformationFlow::iInformationFlowSourceToUMLConnectorEnd():uml::ConnectorEnd{
var end1:umlrpy::End1_Type:=self.end1_;
var end1ObjectPort:umlrpy::IInstance:=self.end1ObjectPort_;
var mappingEnd1:uml::Element;
var mappingEnd1ObjectPort:uml::Element;
//1. we manage the end1 property
if(end1<>null){
if(end1.oclIsTypeOf(umlrpy::IPart)){
mappingEnd1:=end1.oclAsType(umlrpy::IPart).map iPartToUMLElement().oclAsType(uml::Property);
}elif(end1.oclIsTypeOf(umlrpy::IAttribute)){
mappingEnd1:=end1.oclAsType(IAttribute).map iVariableToUMLElement();
}elif(end1.oclIsKindOf(umlrpy::IRelation)){
mappingEnd1:=end1.oclAsType(IRelation).map iRelationToUMLElement();
};
};
//2. we manage the end1ObjectPort_ property when required
if(end1ObjectPort<>null and end1ObjectPort.oclIsKindOf(umlrpy::IRelation)){
mappingEnd1ObjectPort:=end1ObjectPort.oclAsType(umlrpy::IRelation).map iRelationToUMLElement().oclAsType(uml::Element);
};
if(mappingEnd1ObjectPort=null){
if(mappingEnd1.oclIsTypeOf(uml::Property)){
role:=mappingEnd1.oclAsType(uml::Property);
}
}else{
if(mappingEnd1ObjectPort.oclIsTypeOf(uml::Property)){
role:=mappingEnd1ObjectPort.oclAsType(uml::Property);
}elif(mappingEnd1ObjectPort.oclIsTypeOf(uml::Port) and mappingEnd1.oclIsTypeOf(uml::Property)){
//not sure, not example for this usecase
role:=mappingEnd1ObjectPort.oclAsType(uml::Property);
partWithPort:=mappingEnd1.oclAsType(uml::Property);
};
};
}
/**
* This method map a IInformationFlow with a UML Connector End used as target
*
*/
mapping umlrpy::IInformationFlow::iInformationFlowTargetToUMLConnectorEnd():uml::ConnectorEnd{
var end2:umlrpy::End1_Type:=self.end2_;
var end2ObjectPort:umlrpy::IInstance:=self.end2ObjectPort_;
var mappingEnd2:uml::Element;
var mappingEnd2ObjectPort:uml::Element;
//1. we manage the end2 property
if(end2<>null){
if(end2.oclIsTypeOf(umlrpy::IPart)){
mappingEnd2:=end2.oclAsType(umlrpy::IPart).map iPartToUMLElement().oclAsType(uml::Property);
}elif(end2.oclIsTypeOf(umlrpy::IAttribute)){
mappingEnd2:=end2.oclAsType(IAttribute).map iVariableToUMLElement();
}elif(end2.oclIsKindOf(umlrpy::IRelation)){
mappingEnd2:=end2.oclAsType(IRelation).map iRelationToUMLElement();
};
};
//2. we manage the end2ObjectPort_ property when required
if(end2ObjectPort<>null and end2ObjectPort.oclIsKindOf(umlrpy::IRelation)){
mappingEnd2ObjectPort:=end2ObjectPort.oclAsType(umlrpy::IRelation).map iRelationToUMLElement().oclAsType(uml::Element);
};
if(mappingEnd2ObjectPort=null){
if(mappingEnd2.oclIsTypeOf(uml::Property)){
role:=mappingEnd2.oclAsType(uml::Property);
}
}else{
if(mappingEnd2ObjectPort.oclIsTypeOf(uml::Property)){
role:=mappingEnd2ObjectPort.oclAsType(uml::Property);
}elif(mappingEnd2ObjectPort.oclIsTypeOf(uml::Port) and mappingEnd2.oclIsTypeOf(uml::Property)){
//not sure, not example for this usecase
role:=mappingEnd2ObjectPort.oclAsType(uml::Property);
partWithPort:=mappingEnd2.oclAsType(uml::Property);
};
};
}
/**
*
* Returns true of the object is a UML Connector
*/
query umlrpy::IInformationFlow::isUMLConnector(): Boolean{
return self.Stereotypes[IStereotype]->select(ste | ste.name="BindingConnector").oclAsSet()->notEmpty()
}
/**
* This method map a IObjectLink with a UML Element
*
*/
mapping umlrpy::IObjectLink::iObjectLinkToUMLElement():uml::Element disjuncts
umlrpy::IObjectLink::iObjectLinkToUMLConnector
{}
/**
* This method map a IObjectLink with a UML Connector
*
*/
mapping umlrpy::IObjectLink::iObjectLinkToUMLConnector():uml::Connector when{self.isUMLConnector() }{
name:= self.name.replaceAll("\"","");
_end+=self.map iObjectLinkSourceToUMLConnectorEnd();
_end+=self.map iObjectLinkTargetToUMLConnectorEnd();
var localComment:Comment:=self.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
* This method map a IObjectLink with a UML Connector End used as source
*
*/
mapping umlrpy::IObjectLink::iObjectLinkSourceToUMLConnectorEnd():uml::ConnectorEnd{
var fromLink:umlrpy::FromLinkType:=self.fromLink;
var fromPort:umlrpy::IRelation:=self.fromPort;
//1. we manage the from link property
if(fromLink<>null){
if(fromLink.oclIsTypeOf(umlrpy::IPart)){
partWithPort:=fromLink.oclAsType(umlrpy::IPart).map iPartToUMLElement().oclAsType(uml::Property);
}elif(fromLink.oclIsTypeOf(umlrpy::IAssociationEnd)){
partWithPort:=fromLink.oclAsType(IAssociationEnd).map toAssociationsEnd();
}elif(fromLink.oclIsKindOf(umlrpy::IRelation)){
role:=fromLink.oclAsType(umlrpy::IRelation).map iRelationToUMLElement().oclAsType(uml::Port);
};
};
//2. we manage the fromPort property when required
if(fromPort<>null and fromPort.oclIsKindOf(umlrpy::IRelation)){
if(role=null){
role:=fromPort.oclAsType(umlrpy::IRelation).map iRelationToUMLElement().oclAsType(uml::Port);
}
//I don't know what to do in other case!
};
if(partWithPort.oclIsTypeOf(Property) and role=null){
role:=partWithPort;
partWithPort:=null;
}
}
/**
* This method map a IObjectLink with a UML Connector End used as target
*
*/
mapping umlrpy::IObjectLink::iObjectLinkTargetToUMLConnectorEnd():uml::ConnectorEnd{
var toLink:umlrpy::FromLinkType:=self.toLink;
var toPort:umlrpy::IRelation:=self.toPort;
//1. we manage the from link property
if(toLink<>null){
if(toLink.oclIsTypeOf(umlrpy::IPart)){
partWithPort:=toLink.oclAsType(umlrpy::IPart).map iPartToUMLElement().oclAsType(uml::Property);
}elif(toLink.oclIsTypeOf(umlrpy::IAssociationEnd)){
partWithPort:=toLink.oclAsType(IAssociationEnd).map toAssociationsEnd();
}elif(toLink.oclIsKindOf(umlrpy::IRelation)){
role:=toLink.oclAsType(umlrpy::IRelation).map iRelationToUMLElement().oclAsType(uml::Port);
};
};
//2. we manage the fromPort property when required
if(toPort<>null and toPort.oclIsKindOf(umlrpy::IRelation)){
if(role=null){
role:=toPort.oclAsType(umlrpy::IRelation).map iRelationToUMLElement().oclAsType(uml::Port);
}
//I don't know what to do in other case!
};
if(partWithPort.oclIsTypeOf(Property) and role=null){
role:=partWithPort;
partWithPort:=null;
}
}
/**
*
* Returns true of the object is a UML Connector
*/
query umlrpy::IObjectLink::isUMLConnector(): Boolean{
return self.isStereotypedWith("connector");
}
mapping umlrpy::IRelation::iRelationToUMLElement():uml::Element disjuncts
umlrpy::IRelation::iRelationToSysMLPort,
umlrpy::IRelation::iRelationToUMLProperty
{}
/**
* This mapping convert a IRelation instanceof ISysMLPort into a uml Property
*
*/
mapping umlrpy::IRelation::iRelationToUMLProperty(): uml::Property when {self.isRpySysMLPortRepresentingUMLProperty()}{
var sysPort:umlrpy::ISysMLPort:=self.oclAsType(ISysMLPort);
name:= sysPort.name.replaceAll("\"","");
aggregation:=AggregationKind::composite;
// if (not sysPort.otherClass.oclIsUndefined()){
// type := sysPort.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
// }elif(sysPort.otherClass.oclIsKindOf(IClass)){
// type := sysPort.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
// };
//at this time we don't generate implicite type
if(sysPort.implicitClass<>sysPort.otherClass){
type := sysPort.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
};
//a multiplicity has been defined
if(not sysPort.multiplicity.oclIsUndefined()){
lowerValue:= createLowerMultiplicity(sysPort.multiplicity);
upperValue:= createUpperMultiplicity(sysPort.multiplicity);
}else{
lowerValue:= createLowerMultiplicity("1");
upperValue:= createUpperMultiplicity("1");
};
var localComment:Comment:=sysPort.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
* This mapping convert a IRelation instanceof ISysMLPort into a uml Port
*
*/
mapping umlrpy::IRelation::iRelationToSysMLPort(): uml::Port when {self.isRpySysMLPortRepresentingUMLPort()}{
var sysPort:umlrpy::ISysMLPort:=self.oclAsType(ISysMLPort);
name:= sysPort.name.replaceAll("\"","");
// if (not sysPort.otherClass.oclIsUndefined()){
// if(sysPort.otherClass.oclIsKindOf(IType)){
// type := sysPort.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
// }elif(sysPort.otherClass.oclIsKindOf(IClass)){
// type := sysPort.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
// }
// };
if(sysPort.implicitClass<>sysPort.otherClass){
type := sysPort.otherClass.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
};
aggregation:=AggregationKind::composite;
//to my mind, the Rpy field isConjugated manage the SysML FlowPort property and the UML one.
//isConjugated:=sysPort.isConjugated();
//a multiplicity has been defined
if(not sysPort.multiplicity.oclIsUndefined()){
lowerValue:= createLowerMultiplicity(sysPort.multiplicity);
upperValue:= createUpperMultiplicity(sysPort.multiplicity);
}else{
lowerValue:= createLowerMultiplicity("1");
upperValue:= createUpperMultiplicity("1");
};
var localComment:Comment:=sysPort.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
query umlrpy::IRelation::isRpySysMLPortRepresentingUMLPort(): Boolean{
if(self.isRpyPort()){
return self.oclAsType(ISysMLPort).Stereotypes[IStereotype]->select(ste | ste.name="flowPort")->notEmpty();
//we could do an additional check, checking that owner is stereotyped by Block?
};
return false;
}
query umlrpy::IRelation::isRpySysMLPortRepresentingUMLProperty(): Boolean{
if(self.isRpyPort()){
return self.oclAsType(ISysMLPort).Stereotypes[IStereotype]->select(ste | ste.name="ConstraintParameter")->notEmpty();
//we could do an additional check, checking that owner is stereotyped by ConstraintParamater?
};
return false;
}
//TODO : merge me with previous one
query umlrpy::IRelation::isRpySysMLPortContraintParameter(): Boolean{
if(self.isRpyPort()){
return self.oclAsType(ISysMLPort).Stereotypes[IStereotype]->select(ste | ste.name="ConstraintParameter")->notEmpty();
//we could do an additional check, checking that owner is stereotyped by ConstraintParamater?
};
return false;
}
mapping umlrpy::IStateChart::toStateMachine(): uml::StateMachine
{
//get hierarchic states
var parentStates:Set(IState) :=self.getCompositeStates();
var allsubStates:Set(IState):= self.getallSubStates();
name:=self.name.replaceAll("\"","");
// create the default region : for the default ROOT region concept did not exist in rhap
region := object Region
{
name:="Region1";
subvertex += self.States[IState]->select(s|allsubStates->excludes(s) and parentStates->excludes(s)).map toStates();
var pseudo := object Pseudostate {
name :="initial";
kind:= PseudostateKind::initial;
};
subvertex+=pseudo;
//only the first default transition
transition += self.Transitions[IDefaultDrvdTrans]->select(t|parentStates->excludes(t.ofState)).map toInitialTransition(pseudo);
subvertex+= self.States[IState]->select(s|parentStates->includes(s)).map toCompositeStates(self);
// only transitions that its states are in the firest regions
transition+=self.Transitions[ITransition]->select(t|((allsubStates->excludes(t.itsTarget.oclAsType(IState))) and (allsubStates->excludes(t.itsSource.oclAsType(IState))))).map toTransitions();
// other mix transition (source and target not in the same region)
transition+=self.getMixTransitions(parentStates, allsubStates).map toTransitions();
};
}
query umlrpy::IStateChart::getMixTransitions(parentStates:Set(umlrpy::IState), allsubStates:Set(umlrpy::IState)): Set(umlrpy::ITransition)
{
var mixTrnasitions:Set(umlrpy::ITransition);
var outTransitions :=self.Transitions[ITransition]->select(t|((allsubStates->excludes(t.itsTarget.oclAsType(IState))) and (allsubStates->excludes(t.itsSource.oclAsType(IState)))));
var innerTransitions := self.Transitions[ITransition]->select(t|allsubStates->includes(t.itsSource.oclAsType(IState)) and allsubStates->includes(t.itsTarget.oclAsType(IState)));
mixTrnasitions := self.Transitions[ITransition]->select(t| (innerTransitions->excludes(t) and outTransitions->excludes(t)));
return mixTrnasitions;
}
query umlrpy::IStateChart::getSubStates(parentstate: umlrpy::IState ): Set(umlrpy::IState)
{
var subStates:Set(umlrpy::IState);
self.States->forEach(state)
{
if (state.parent.oclAsType(IState)=parentstate)
{
subStates+=state.oclAsType(IState);
}
};
return subStates;
}
query umlrpy::IStateChart::getCompositeStates(): Set(umlrpy::IState)
{
var parentStates:Set(umlrpy::IState);
self.States->forEach(state)
{
if (not(state.parent.oclAsType(IState).name.replaceAll("\"","")="ROOT"))
{
parentStates+=state.parent.oclAsType(IState);
}
};
return parentStates;
}
query umlrpy::IStateChart::getallSubStates(): Set(umlrpy::IState)
{
var allSubStates:Set(umlrpy::IState);
self.States->forEach(state)
{
if (not(state.parent.oclAsType(IState).name.replaceAll("\"","")="ROOT"))
{
allSubStates+=state.oclAsType(IState);
}
};
return allSubStates;
}
mapping umlrpy::IDefaultDrvdTrans::toInitialTransition(pseudo:uml::Vertex): uml::Transition
{
name:=self.name;
target:= self.itsTarget[IState].resolveone(State);
source:=pseudo;
}
mapping umlrpy::IState::toCompositeStates(statechart:umlrpy::IStateChart): uml::State
{
var allsubStates:Set(IState):= statechart.getSubStates(self);
name:=self.name.replaceAll("\"","");
result.oclAsType(State).region:= object Region
{
name:="Region1";
subvertex += allsubStates.map toStates();
var pseudo := object Pseudostate {
name :="initial";
kind:= PseudostateKind::initial;
};
subvertex+=pseudo;
transition += statechart.Transitions[IDefaultDrvdTrans]->select(t|t.ofState=self).map toInitialTransition(pseudo);
transition += statechart.Transitions[ITransition]->select(t|allsubStates->includes(t.itsSource.oclAsType(IState)) and allsubStates->includes(t.itsTarget.oclAsType(IState))).map toTransitions();
}
}
mapping umlrpy::IState::toStates(): uml::State
when {not(self.name.replaceAll("\"","")="ROOT")}
{
name:=self.name.replaceAll("\"","");
}
mapping umlrpy::ITransition::toTransitions(): uml::Transition
{
name:=self.name;
target:= self.itsTarget[IState].resolveone(State);
source:=self.itsSource[IState].resolveone(State);
trigger:=self.itsLabel[ILabel].itsTrigger [IInterfaceItemTrigger].map toTrigger();
//take the first guard
guard:=self.itsLabel[ILabel].itsGuard[IGuard]->any(true).map toGuard();
effect:= self.itsLabel[ILabel].itsAction[IAction]->any(true).map toBehavior();
}
mapping umlrpy::IAction::toBehavior(): uml::OpaqueBehavior
{
body:=self.body.trim();
language:= "C++";
}
mapping umlrpy::IGuard::toGuard(): uml::Constraint
{
result.specification := object OpaqueExpression
{
body:=self.body.trim();
language:= "C++";
}
}
mapping umlrpy::IInterfaceItemTrigger::toTrigger(): uml::Trigger
{
event:= self.itsInterfaceItem.resolveone(SignalEvent);
}
mapping umlrpy::IGeneralization::toPapyrusGeneralization(): uml::Generalization
{
general:= self.oclAsType(IGeneralization).dependsOn.oclAsType(IClass).oclAsType(EObject).map iClassToUMLClass();
}
mapping umlrpy::IReception::toReceptions(): uml::Reception
{
name:= self.event.name.replaceAll("\"","");
signal := self.event[IEvent].resolveone(Signal);
}
mapping umlrpy::IPrimitiveOperation::toOperations(): uml::Operation
{
name:= self.name.replaceAll("\"","");
// with the return type inside
ownedParameter:= self.Args[IArgument]->map toArguments();
if (not self.returnType.oclIsUndefined()){
var return_param:= object uml::Parameter {
direction:= ParameterDirectionKind::_return;
type:= self.returnType.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
};
ownedParameter+=return_param;
};
var desiredVisibility := getVisibility(self.protection);
if (desiredVisibility != VisibilityKind::public) { //to avoid green + in UML editor
visibility:= desiredVisibility
};
}
mapping umlrpy::IVariable::iVariableToUMLElement():uml::Property disjuncts
umlrpy::IArgument::iArgumentToUMLElement,
umlrpy::IAttribute::iAttributeToUMLElement
{}
mapping umlrpy::IArgument::iArgumentToUMLElement(): uml::Property when {self.oclIsTypeOf(umlrpy::IArgument)}{
name:= self.oclAsType(IArgument).name.replaceAll("\"","");
// should add the PtR Stereotpe if the type is a C++ Declaration : i,e: Class *;
if (self.typeOf.oclIsUndefined()){
type := self.myTypeOf.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
userTypeDeclaration+=type;
}else{
type := self.typeOf.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
};
var localComment:Comment:=self.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
* We map IAttribute declared in the TopLevel class as instance specifications
*/
helper umlrpy::IAttribute::isInstanceSpecification():Boolean{
var owner:EObject:=self.oclAsType(EObject).eContainer();
return owner.oclIsKindOf(IClass) and owner.oclAsType(IClass).name="TopLevel";
}
/**
* This mapping creates InstanceSpecification from IAttribute
*/
mapping ecore::EObject::iAttributeToUMLInstanceSpecification(): uml::InstanceSpecification when {self.oclIsKindOf(IAttribute) and self.oclAsType(IAttribute).isInstanceSpecification()}{
var iAttribute:IAttribute:=self.oclAsType(IAttribute);
name:=iAttribute.name;
classifier+=iAttribute.typeOf.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Classifier);
var tmp:String:="";
if(not iAttribute.ValueSpecifications.oclIsUndefined()){
tmp:=iAttribute.ValueSpecifications.value;
};
if(classifier->any(true).oclIsTypeOf(Enumeration)){
specification:=object InstanceValue{
name:="InstanceValue1";
instance:=classifier.oclAsType(Enumeration).member->any(name=tmp).oclAsType(InstanceSpecification);
}
}else{
specification:=object OpaqueExpression{
body:=tmp;
}
};
var desiredVisibility := getVisibility(iAttribute.protection);
if (desiredVisibility != VisibilityKind::public) { //to avoid green + in UML editor
visibility:= desiredVisibility
};
var localComment:Comment:=iAttribute.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
mapping umlrpy::IAttribute::iAttributeToUMLElement(): uml::Property when {self.oclIsTypeOf(umlrpy::IAttribute)}{
name:= self.name.replaceAll("\"","");
// should add the PtR Stereotpe if the type is a C++ Declaration : i,e: Class *;
if (self.typeOf.oclIsUndefined()) {
type := self.myTypeOf.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
userTypeDeclaration+=type;
}else{
type := self.typeOf.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
};
var desiredVisibility := getVisibility(self.protection);
if (desiredVisibility != VisibilityKind::public) { //to avoid green + in UML editor
visibility:= desiredVisibility
};
//a multiplicity has been defined
if(not self.multiplicity.oclIsUndefined()){
lowerValue:= createLowerMultiplicity(self.multiplicity);
upperValue:= createUpperMultiplicity(self.multiplicity);
};
aggregation:=AggregationKind::composite;
var localComment:Comment:=self.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
/**
* Create LiteralInteger to represent the lower multiplicity
*/
helper createLowerMultiplicity(multiplicity:String):LiteralInteger{
if(multiplicity.oclIsUndefined() or multiplicity.size()=0){
return null;
};
var lower:String;
if(multiplicity.indexOf("..")<>0){
lower:=multiplicity.substringBefore("..");
}elif(multiplicity.indexOf(",")<>0){
lower:=multiplicity.substringBefore(",");
}else{
lower:=multiplicity;
};
var lit:LiteralInteger:= object LiteralInteger{};
lit.value:=lower.toInteger();
return lit;
}
/**
* Create LiteralUnlimitedNatural to represent the upper multiplicity
*/
helper createUpperMultiplicity(multiplicity:String):LiteralUnlimitedNatural{
if(multiplicity.oclIsUndefined() or multiplicity.size()=0){
return null;
};
var upper:String;
if(multiplicity.indexOf("..")<>0){
upper:=multiplicity.substringAfter("..");
}elif(multiplicity.indexOf(",")<>0){
upper:=multiplicity.substringAfter(",");
}else{
upper:=multiplicity;
};
var lit:LiteralUnlimitedNatural:= object LiteralUnlimitedNatural{};
if(upper.equalsIgnoreCase("*")){
lit.value:=-1;
}else{
lit.value:=upper.toInteger();
};
return lit;
}
/**
* Return the visibility kind for an IAttribtue or an operation
*/
helper getVisibility(protection:String):uml::VisibilityKind{
if(protection="iPublic"){
return VisibilityKind::public;
}elif(protection="iProtected"){
return VisibilityKind::protected;
}elif(protection="iPrivate"){
return VisibilityKind::private;
};
//seems not possible in Rpy
// elif(self.protection="iPackage"){
// return VisibilityKind::package;
// };
return VisibilityKind::public;
}
mapping umlrpy::IArgument::toArguments(): uml::Parameter
{
name:= self.name.replaceAll("\"","");
direction:= getDirectionKind(self.argumentDirection);
// should add the PtR Stereotpe if the type is a C++ Declaration : i,e: Class *;
if (self.typeOf.oclIsUndefined())
{
type := self.myTypeOf.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
userTypeDeclaration+=type;
}else
{
type := self.typeOf.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(Type);
}
}
query getDirectionKind(s:String): uml::ParameterDirectionKind{
var direction: uml::ParameterDirectionKind;
direction:= switch {
case (s="in") ParameterDirectionKind::_in;
case (s="out") ParameterDirectionKind::_out;
case (s="inout") ParameterDirectionKind::_inout;
// there is no return direction in Rpy there is a returnType attribute instead,
};
return direction;
}
mapping umlrpy::IEvent::toSignalEvents(): uml::SignalEvent
{
name:= self.name.replaceAll("\"","");
signal:= self[IEvent].resolveone(Signal); //TODO replace me with a mapping
}
mapping ecore::EObject::iEventToUMLSignal(): uml::Signal when {self.oclIsTypeOf(IEvent)}{
var localEvent:IEvent:=self.oclAsType(IEvent);
name:= localEvent.name.replaceAll("\"","");
ownedAttribute += localEvent.Args[IVariable]->map iVariableToUMLElement();
var localComment:Comment:=localEvent.description.oclAsType(EObject).map generalMappingToUMLElement().oclAsType(uml::Comment);
localComment.annotatedElement:=result;
ownedComment+=localComment;
}
//collect the call events from the umlrpy file
query umlrpy::ISubsystem::callEvents() : Set(umlrpy::IEvent)
{
return self.Events.oclAsType(Set(IEvent))->asSet();
}
//collect the signal events from the umlrpy file
query umlrpy::ISubsystem::SignalEvents() : Set(umlrpy::IEvent)
{
var allSignalEvents : Set(umlrpy::IEvent);
var classes : Set(umlrpy::IClass) :=inModel.rootObjects()[IProject].defaultSubsystem[ISubsystem].Classes[IClass]->asSet();
classes->forEach(classe)
{
if (not(classe.Operations[IReception]->isEmpty()))
{
classe.Operations[IReception]->forEach(reception)
{
if (not(reception.oclAsType(IReception).event.oclIsUndefined()))
allSignalEvents+= reception.oclAsType(IReception).event;
}
}endif;
};
return allSignalEvents;
}