blob: 90816c7ea0f4636ed41ff48db066dab86f3adccd [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013, 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
import org.eclipse.papyrus.interoperability.common.utils.UI;
import org.eclipse.papyrus.interoperability.common.utils.NotationTypes;
import libraries.EclipseUI;
import org.eclipse.papyrus.interoperability.rsa.RTMappings;
import org.eclipse.papyrus.interoperability.common.blackboxes.emf.EMFResource;
modeltype notation "strict" uses 'http://www.eclipse.org/gmf/runtime/1.0.2/notation';
modeltype umlNotation "strict" uses 'http://www.eclipse.org/papyrus/umlnotation';
modeltype uml "strict" uses 'http://www.eclipse.org/uml2/5.0.0/UML';
modeltype ecore "strict" uses 'http://www.eclipse.org/emf/2002/Ecore';
modeltype sash "strict" uses 'http://www.eclipse.org/papyrus/0.7.0/sashdi';
modeltype config "strict" uses 'http:///RSAToPapyrusParameters.ecore';
/**
* Transformation rules for importing an RSA Semantic model into Papyrus (SashModel + cleanup semantics)
*/
transformation RSAModelToPapyrus(inout semantics : uml, inout graphics : notation, out di : sash, in param : config);
main() {
assert fatal (not semantics.rootObjects()[uml::Element]->isEmpty()) with log('Cannot find root uml::Element');
//semantics.objectsOfType(Element).map deleteSourceDiagrams(); //TODO programatically to clean up everything (Avoid memory leaks)
if param.rootObjects()[Config]->any(true).convertOpaqueExpressionToLiteralString then
semantics.objectsOfType(OpaqueExpression).map convertToLiteralString()
endif;
semantics.objectsOfType(OpaqueExpression).map fixLanguage();
semantics.objectsOfType(Stereotype).map fixBaseProperties(); //Bug 492872: Multiplicity change between UML 2.3 (RSA) and 2.4+ (Papyrus)
}
//If the OpaqueExpression doesn't have a language, and a single body, replace it with a LiteralString
mapping inout OpaqueExpression::convertToLiteralString() : LiteralString when {
(self.language->size() = 0 and self.body->size() <= 1) or
(self.language->size() = 1 and self.body->size() <= 1 and
self.language->at(1).isEmpty()
)
} {
init {
result := self.map toLiteralString() //Blackbox cast: Transform OpaqueExpression to LiteralString (Preserve incoming references and compatible features)
}
result.value := if self.body->size() = 0 then null else self.body->at(1) endif;
self.oclAsType(EObject).forceDelete(true); //Destroy the source OpaqueExpression
worked(1);
}
intermediate class Opaque {
language: String;
body: String;
}
mapping inout OpaqueExpression::fixLanguage() when {
(self.language->size() > 1 or self.body->size() > 1) and
(self.language->exists(isEmpty()) or self.language.size() <> self.body.size())
} {
//Replace empty languages by "Undefined" (In Papyrus, "Empty" is interpreted as "OCL", which is the default. This is not the case in RSA, where "Empty" means "Undefined")
var maxSize : Integer := self.language->size().max(self.body->size());
var newLanguages : OrderedSet(Opaque) := OrderedSet{};
var i : Integer = 1;
while(i <= maxSize) {
var lang : String := self.language->at(i);
var body : String := self.body->at(i);
var newLanguage := object Opaque{};
newLanguage.language := if lang.oclIsInvalid() or lang.isEmpty() then 'Undefined' else lang endif;
newLanguage.body := if body.oclIsInvalid() or body.isEmpty() then '' else body endif;
newLanguages += newLanguage;
i := i+1;
};
self.language := newLanguages.language;
self.body := newLanguages.body;
}
//Bug 492872: Multiplicity change between UML 2.3 (RSA) and 2.4+ (Papyrus)
mapping inout Stereotype::fixBaseProperties() when {
self.baseProperties()->size() > 1
}{
self.baseProperties().map fixMultiplicity();
}
mapping inout Property::fixMultiplicity() {
if (not self.lowerValue.oclIsUndefined()) and self.lowerValue.oclIsKindOf(LiteralInteger) then
self.lowerValue.oclAsType(LiteralInteger).value := 0
else
self.lowerValue := object LiteralInteger {
value := 0;
}
endif;
if (not self.upperValue.oclIsUndefined()) and self.upperValue.oclIsKindOf(LiteralUnlimitedNatural) then
self.upperValue.oclAsType(LiteralUnlimitedNatural).value := 1
elif (not self.upperValue.oclIsUndefined()) and self.upperValue.oclIsKindOf(LiteralInteger) then
self.upperValue.oclAsType(LiteralInteger).value := 1
else
self.upperValue := object LiteralUnlimitedNatural {
value := 1;
}
endif;
}
query String::isEmpty() : Boolean {
return self.oclIsUndefined() or self = '';
}
query Stereotype::baseProperties() : Set(Property){
return self.ownedAttribute->select(p | p.name.startsWith("base_") and p.type.oclIsTypeOf(Class)) //Typed with a UML Metaclass
}