Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 6081fe4be4eb035726ad20aaa7c29f61f69ce0a9 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
modeltype UML uses "http://www.eclipse.org/uml2/5.0.0/UML";
modeltype PropertyContext uses "http://www.eclipse.org/papyrus/properties/contexts/0.9";
modeltype PropertyEnvironment uses "http://www.eclipse.org/papyrus/properties/environment/0.9";
modeltype PRoot uses "http://www.eclipse.org/papyrus/properties/root";
modeltype Constraints uses "http://www.eclipse.org/papyrus/constraints/0.9";

transformation stereotype2datacontext(in profile : UML, out context : PropertyContext, in uml : PropertyContext, in pRoot : PRoot);

main() {
	profile.rootObjects()[Profile]->map toContext();
}

----- Context -----

mapping Package::toContext() : Context{
	name := self.name;
	dataContexts := self.map toDCRoot();
	dependencies := uml.rootObjects()[Context];
	self.getClassifiers()->map toDCElement();
}

query Package::getRootPackage() : Package {
	var package : Package;
	if self.nestingPackage.oclIsUndefined() then 
		package := self
	else
		package := self.nestingPackage.getRootPackage()
	endif;
	return package;
}

query Classifier::getRootPackage() : Package {
	return self.package.getRootPackage();
}

query Package::getClassifiers() : Collection(Classifier) {
	return self.packagedElement->select(e | e.isView()).oclAsType(Classifier);
}

-------------------

----- DataContextPackage & DataContextRoot -------

mapping Package::toDCPackage() : DataContextPackage disjuncts
	Package::toDataContextPackage, Package::toDCRoot;
	
abstract mapping Package::toAbstractDCPackage() : DataContextPackage {
	name := self.name;
	
	var mappedElements := self.getClassifiers().map toDCElement(); 
	
	elements := mappedElements.element
		->union(
			self.packagedElement->select(e | e.oclIsKindOf(Package)).oclAsType(Package)->map toDataContextPackage()
		)
	;
}

mapping Package::toDataContextPackage() : DataContextPackage inherits Package::toAbstractDCPackage when {
	not self.nestingPackage.oclIsUndefined()
}{
	if not self.nestingPackage.oclIsUndefined() then
		package := self.nestingPackage.map toDataContextPackage()
	endif;
}

mapping Package::toDCRoot() : DataContextRoot disjuncts Model::toDataContextRoot, Profile::toDatacontextRoot when {
	self.nestingPackage.oclIsUndefined();
};

mapping Model::toDataContextRoot() : DataContextRoot inherits Package::toAbstractDCPackage {
	modelElementFactory := findFactory('org.eclipse.papyrus.uml.properties.modelelement.UMLModelElementFactory');
}

mapping Profile::toDatacontextRoot() : DataContextRoot inherits Package::toAbstractDCPackage{
	modelElementFactory := findFactory('org.eclipse.papyrus.uml.properties.modelelement.StereotypeModelElementFactory');
}

query findFactory(className : String) : ModelElementFactoryDescriptor {
	return pRoot.rootObjects()[PropertiesRoot].environments.modelElementFactories
			->any(e | e.factoryClass = className);
}

--------------------------------------------------

----- DataContextElement & View -------

mapping Classifier::toDCElement() : element : DataContextElement, viewSingle : View, viewMultiple : View 
	disjuncts Stereotype::toDataContextElement, DataType::toDataContextElement;
	
abstract mapping Classifier::toAbstractDCElement() : element : DataContextElement, viewSingle : View, viewMultiple : View{
	element.name := self.name;
	element.package := self.package.map toDCPackage();

	viewSingle.name := 'Single '+self.name;
	viewSingle.automaticContext := true;
	viewSingle.datacontexts := element;
	viewSingle.elementMultiplicity := 1;
	viewSingle.constraints := self.map toConstraint(viewSingle);
	viewSingle.context := self.getRootPackage().map toContext();
	
	viewMultiple.name := 'Multiple '+self.name;
	viewMultiple.automaticContext := true;
	viewMultiple.datacontexts := element;
	viewMultiple.elementMultiplicity := -1;
	viewMultiple.constraints := self.map toConstraint(viewMultiple);
	viewMultiple.context := self.getRootPackage().map toContext();
}

mapping Stereotype::toDataContextElement() : element : DataContextElement, viewSingle : View, viewMultiple : View inherits Classifier::toAbstractDCElement{
	element.properties := self.attribute->select(e | e.isAttribute(self))->map toProperty();
	element.supertypes := self.generalization.target->select(e | e.isView()).oclAsType(Classifier)->map toDCElement().element->union(
		self.ownedAttribute->select(e | not e.isAttribute(self)).getDataContextElement()->asSet()
	);
}

mapping DataType::toDataContextElement() : element : DataContextElement, viewSingle : View, viewMultiple : View inherits Classifier::toAbstractDCElement when {
	self.oclIsTypeOf(DataType) -- Exclude primitive types from generation
}{
	element.properties := self.attribute->map toProperty();
	element.supertypes := self.generalization.target->select(e | e.isView()).oclAsType(Classifier)->map toDCElement().element->union(
		self.ownedAttribute->getDataContextElement()->asSet()
	);
}

mapping Classifier::toConstraint(view : View) : SimpleConstraint{
	name := "is" + view.name.replace(' ', '');
	display := view;
	constraintType := pRoot.objectsOfType(PropertiesRoot).environments.constraintTypes->any(e | e.constraintClass = 'org.eclipse.papyrus.uml.properties.constraints.HasStereotypeConstraint');
	var stereotypeName := object ValueProperty {
		name := 'stereotypeName';
		value := self.qualifiedName;
	};
	properties := stereotypeName;
}

query Element::isView() : Boolean {
	return self.oclIsTypeOf(Stereotype) or self.oclIsTypeOf(DataType);
}

query Property::getDataContextElement() : DataContextElement {
	var extension := self.association.memberEnd->any(e | not self.association.ownedEnd->includes(e));
	var metaclassName := extension.type.name;
	return uml.rootObjects()[Context].dataContexts->any(e | e.name = 'UML').elements->any(e | e.name = metaclassName);
}

query UML::Property::isAttribute(stereo : Stereotype) : Boolean{
	return not self.name.startsWith('base_');
}

---------------------------------------

mapping UML::Property::toProperty() : PropertyContext::Property {
	name := self.name;
	type := self.type.getType();
	multiplicity := if self.upperBound() > 1 or self.upperBound() = -1 then -1 else 1 endif;
	
	description := profile.objectsOfType(UML::Comment)->select(comment | comment.annotatedElement->includes(self))->any(comment | true).body
}

query UML::Type::getType() : PropertyEnvironment::Type {
	-- Unknown cases are handled as Strings
	var type : PropertyEnvironment::Type := PropertyEnvironment::Type::String;
	switch {
		case (self.oclIsKindOf(Class)) type := PropertyEnvironment::Type::Reference;
		case (self.oclIsKindOf(Enumeration)) type := PropertyEnvironment::Type::Enumeration;
		case (self.oclIsKindOf(PrimitiveType)) switch {
			case (self.name = "String") type := PropertyEnvironment::Type::String; 
			case (self.name = "Integer") type := PropertyEnvironment::Type::Integer;
			case (self.name = "Boolean") type := PropertyEnvironment::Type::Boolean;
			case (self.name = "Real") type := PropertyEnvironment::Type::String;
		};
		case (self.oclIsTypeOf(DataType)) type := PropertyEnvironment::Type::Reference;
	};
	return type;
}

Back to the top