Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: cb87ed4a6490586283cc7ab10d5971d45682b9df (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*****************************************************************************
 * 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.m2m.qvto.UI;
import org.eclipse.papyrus.m2m.qvto.NotationTypes;
import libraries.EclipseUI;
import org.eclipse.papyrus.migration.rsa.RTMappings; 
import org.eclipse.papyrus.m2m.qvto.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
}

Back to the top