Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 29e7a77fc78e1e24a826deac1f2ac610dc8e7aa4 (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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
--/*******************************************************************************
-- * Copyright (c) 2015 Vienna University of Technology.
-- * 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:
-- * Alexander Bergmayr (TU Wien) - initial API and implementation
-- * Manuel Wimmer (TU Wien) - initial API and implementation 
-- *
-- * Initially developed in the context of ARTIST EU project www.artist-project.eu
-- *******************************************************************************/

-- @nsURI UMLMM=http://www.eclipse.org/uml2/3.0.0/UML
-- @path JMM=pathmap://METAMODEL/java.ecore

library javaLibrary;

helper context JMM!TypeAccess def : getParameterizedType() : UMLMM!Type =
	-- BUG: TODO : we need to deal with UnresolvedTypeDeclaration! 
--	if(self.oclIsTypeOf(JMM!UnresolvedTypeDeclaration)) then OclUndefined
--	else
		thisModule.resolveTemp(self.type, 't1');
--	endif;
	
--helper context JMM!TypeAccess def : containedByModelLibrary() : Boolean =
--	UMLMM!Type.allInstancesFrom('ML') -> exists(e | e.name = self.type.name and e.refImmediateComposite().name = self.type.refImmediateComposite().name);

-- checks if a type is complex
helper context JMM!TypeAccess def : isComplexType() : Boolean =
	if(self.isPrimitiveType() or self.type.oclIsTypeOf(JMM!EnumDeclaration)) then false
	else
		if(self.type.oclIsTypeOf(JMM!ArrayType)) then not self.type.isArrayWithNonComplexType
		else
			true
		endif
	endif;

-- ckecks if a type is primitive ...
helper context JMM!TypeAccess def : isPrimitiveType() : Boolean =
	-- if we have a kind of PrimitiveType (int, float, bool, etc.)
	if (self.type.oclIsKindOf(JMM!PrimitiveType)) then true
	else
		-- wrapped primitive types (e.g., ClassDeclaration of type String etc.)
		if ((self.type.name = 'String') or (self.type.name = 'Integer') 
				or (self.type.name = 'Long') or (self.type.name = 'Short')
				or (self.type.name = 'Float') or (self.type.name = 'Double')
				or (self.type.name = 'Boolean') or (self.type.name = 'Number')) then true
		else
			-- finally, we have the case of Array's with primitive type
			-- only in case it is an ArrayType, we check the type of the Array
			if(not self.type.oclIsTypeOf(JMM!ArrayType)) then false
			else
				--if (self.type.elementType.isPrimitiveType() or self.type.elementType.type.oclIsTypeOf(JMM!EnumDeclaration)) then true
				if(self.type.elementType.isPrimitiveType()) then true
				else
					false
				endif
			endif
		endif
	endif;
				
helper context JMM!TypeAccess def : isParameterizedType : Boolean = 
	self.type.oclIsTypeOf(JMM!ParameterizedType) or self.type.isJavaLangClass();
	
helper context OclAny def : isJavaLangClass : Boolean =
	self.refImmediateComposite().getFullyQualifiedPackageName.toString().concat('.').concat(self.name).toString() = 'java.lang.Class' or
	self.refImmediateComposite().getFullyQualifiedPackageName.toString().concat('.').concat(self.name).toString() = 'java.lang.Class[]';
	
helper context JMM!ArrayType def : isArrayWithNonComplexType : Boolean =
	if (self.elementType.isPrimitiveType() or self.elementType.type.oclIsTypeOf(JMM!EnumDeclaration)) then true
	else false
	endif;
	
-- TODO: here we could also use a Map
-- returns the type for a given type access; required to determine on the return type of
-- a method in the annotation type declaration
helper context JMM!TypeAccess def : getType() : UMLMM!Type =
	-- PrimitiveType, String
	if self.isPrimitiveType() then self.type.getTypeFromPrimitiveType
	else
		-- Class / Parameterized Class (can only be java.lang.Class)
		if (self.type.oclIsTypeOf(JMM!ClassDeclaration) or self.type.oclIsTypeOf(JMM!ParameterizedType)) then self.type.getTypeFromTypeDeclaration
		else
			-- EnumType
			if self.type.oclIsTypeOf(JMM!EnumDeclaration) then self.type.getTypeFromEnumDeclaration()
			else
				-- AnnotationType
				if self.type.oclIsTypeOf(JMM!AnnotationTypeDeclaration) then self.type.getTypeFromAnnotationTypeDeclaration()
				else
					-- ArrayType
					if self.type.oclIsTypeOf(JMM!ArrayType) then self.type.getTypeFromArrayType
					
					-- UnresolvedType
					else thisModule.resolveTemp(self.type, 't1')
					endif
				endif
			endif
		endif
	endif;

-- return for a given Java
-- we should use here Java Primitive Types ... ????
helper context JMM!Type def : getTypeFromPrimitiveType : UMLMM!Type =
	thisModule.javaPrimitiveType.get(self.name.toString());

-- can only be java.lang.Class
helper context OclAny def : getTypeFromTypeDeclaration : UMLMM!Type =
	UMLMM!Class.allInstancesFrom('MC') -> any(e | e.name = 'Class');
	
-- return for a given Java parameterized Class the appropriate UML Class
helper context JMM!ParameterizedType def : getTypeFromParameterizedType() : UMLMM!Class =
	UMLMM!Class.allInstancesFrom('MC') -> any(e | e.name = 'Class');

-- return for a given Java Enum Type the appropriate UML instance of this Enum Type
helper context JMM!EnumDeclaration def : getTypeFromEnumDeclaration() : UMLMM!Enumeration =
	thisModule.resolveTemp(self, 't1');

-- return for a given Java Annotation Type the appropriate UML instance of this 
helper context JMM!AnnotationTypeDeclaration def : getTypeFromAnnotationTypeDeclaration() : UMLMM!Stereotype =
	thisModule.resolveTemp(self, 't1');

-- return for a given Java Annotation Type the appropriate UML instance of this 
helper context JMM!UnresolvedTypeDeclaration def : getTypeFromUnresolvedTypeDeclaration() : UMLMM!Class =
	thisModule.resolveTemp(self, 't1');

-- return for a given Java ArrayType the appropriate UML Type  ... here deal only with
-- complex types and enumerations
helper context JMM!ArrayType def : getTypeFromArrayType : UMLMM!Type =	
	if(self.elementType.type.oclIsTypeOf(JMM!ClassDeclaration) or
	   self.elementType.type.oclIsTypeOf(JMM!InterfaceDeclaration)) then 
	   		self.elementType.type.getTypeFromTypeDeclaration
	else
		if(self.elementType.type.oclIsTypeOf(JMM!ParameterizedType)) then
			self.elementType.type.getTypeFromParameterizedType()
		else
			if(self.elementType.type.oclIsTypeOf(JMM!EnumDeclaration)) then
				self.elementType.type.getTypeFromEnumDeclaration()
			else
				if(self.elementType.type.oclIsTypeOf(JMM!AnnotationTypeDeclaration)) then 
					self.elementType.type.getTypeFromAnnotationTypeDeclaration()
				else
					if(self.elementType.type.oclIsTypeOf(JMM!UnresolvedTypeDeclaration)) then
						self.elementType.type.getTypeFromUnresolvedTypeDeclaration()
					else
						-- TODO: check ... but should actually not happen ;)
						OclUndefined
					endif
				endif
			endif
		endif
	endif;

-- decide if a class or interface is required for the annotation type declaration
--helper context JMM!Type def : isRequiredForAnnotationTypes : Boolean = 
--	if (JMM!AnnotationTypeMemberDeclaration.allInstances() ->
--			select(e | e.type.type.oclIsTypeOf(JMM!ParameterizedType)) -> exists(f | f.type.type.typeArguments -> exists(g | g.type.name = s1.name)) or
--		
--		
--	)

--  get fully qualified package name of a java type
helper context OclAny def : getFullyQualifiedPackageName : String =
	if(self.refImmediateComposite().oclIsTypeOf(JMM!Package)) then 
	   self.refImmediateComposite().getFullyQualifiedPackageName.concat('.').concat(self.name)
	else
	   self.name
	endif;

-- get Java package
helper context OclAny def : getJavaPackage() : JMM!Package =
	if(not self.package.oclIsUndefined()) then
		self.package
	else
		self.refImmediateComposite().getPackage()
	endif;

-- get the package of a PackageableElement
helper context UMLMM!PackageableElement def : getPackage() : UMLMM!Package =
	if(self.refImmediateComposite().oclIsTypeOf(UMLMM!Package)) then
		self.refImmediateComposite()
	else
		self.refImmediateComposite().getPackage()
	endif;
	
-- only those code elements that are relevant element types / return values of annotation type declarations
helper context OclAny def : isRelevantForAnnotationTypes : Boolean =
	-- maybe the name matching here can be dangerous ...
	if(self.oclIsKindOf(JMM!Type)) then
		if ((self.oclIsTypeOf(JMM!AnnotationTypeDeclaration) and self.proxy = false)) or
		    
			(thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined())
		    	-> exists(e | e.type.type = self) or
				
		    (thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined())
		    	-> select(e | e.type.type.oclIsTypeOf(JMM!ArrayType)))
		    	-> exists(e | e.type.type.elementType.type = self) or
				
			self.hasInnerAnnotationTypeDeclaration()
		    
		    ) then true
		else false endif
	else false
	endif;

-- we want to have only packages that serve as container for annotation type declarations
helper context JMM!Package def : isAnnotationTypeContainer : Boolean =
	if self.ownedElements -> exists(e | e.isRelevantForAnnotationTypes) or 
	   self.ownedPackages -> exists(e | e.isAnnotationTypeContainer) then true
	else false
	endif;

helper context JMM!Type def : hasInnerAnnotationTypeDeclaration() : Boolean =
	if(self.bodyDeclarations -> exists(e | e.oclIsTypeOf(JMM!AnnotationTypeDeclaration)) or
	   self.bodyDeclarations -> select(e | e.oclIsKindOf(JMM!Type)) -> exists(f | f.hasInnerAnnotationTypeDeclaration())
	) then true
	else false
	endif;
		
helper context OclAny def : isEnumerationRelevant : Boolean =
	 -- must be an EnumerationType
	 if(not self.oclIsTypeOf(JMM!EnumDeclaration)) then false
	 else
	
	 -- the Enumeration is the type of an AnnotationTypeMemberDeclaration
	 thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined()) ->
	    exists(e | e.type.type = self) or
	
	 -- the Enumeration is the element type of an Array which is the type of an AnnotationTypeMemberDeclaration 
	 thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined()) ->
	 	select(e | e.type.type.oclIsTypeOf(JMM!ArrayType)) ->
		exists(f | f.type.type.elementType.type = self) or
	 
	 -- the Enumeration is the parameter of java.lang.Class which is the type of an AnnotationTypeMemberDeclaration
	 thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined()) ->
	    select(e | e.type.type.oclIsTypeOf(JMM!ParameterizedType)) -> 
		exists(f | f.type.type.typeArguments -> exists(g | g.type = self))
	 
	 endif;

-- required because the structure of the model differs depending on multi-valued vs. single-valued SingleVariableAccess elements 
helper context JMM!SingleVariableAccess def : isMultiValuedAnnotationTarget : Boolean =
	if self.refImmediateComposite().refImmediateComposite().refImmediateComposite().oclIsTypeOf(JMM!Annotation) then
	   self.refImmediateComposite().refImmediateComposite().refImmediateComposite().type.type.name = 'Target'
	else false
	endif;

-- required because the structure of the model differs depending on multi-valued vs. single-valued SingleVariableAccess elements 
helper context JMM!SingleVariableAccess def : isSingleValuedAnnotationTarget : Boolean =
	if self.refImmediateComposite().refImmediateComposite().oclIsTypeOf(JMM!Annotation) then
	   self.refImmediateComposite().refImmediateComposite().type.type.name = 'Target'
	else false
	endif;

-- mapping between java element type targets and UML targets, i.e., the extended UML element
helper def : umlTarget : Map(String, Sequence(UMLMM!Element)) = 
	Map{
		('ANNOTATION_TYPE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Stereotype').first()}),
	    -- TODO: add constraint
		('CONSTRUCTOR', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Operation').first()}),
		-- maybe we could think also to annotate the association on a model level ... however
		-- for this prototype we do not consider associations at all .. so it is sufficient to
		-- have here Property only.
		('FIELD', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Property').first(),
			               UMLMM!Type.allInstances() -> select(e | e.name = 'EnumerationLiteral').first()--,
--			               UMLMM!Type.allInstances() -> select(e | e.name = 'Association').first()
							}),					
	    ('LOCAL_VARIABLE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Property').first()--,
			                        -- UMLMM!Type.allInstances() -> select(e | e.name = 'Association').first()
									}),
		('METHOD', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Operation').first(),
							UMLMM!Type.allInstances() -> select(e | e.name = 'Property').first()
							}),
		('PACKAGE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Package').first()}),
	    ('PARAMETER', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Parameter').first()}),
		-- adaptation required ... Java Type --> Class, Interface, AnnotationType, Enumeration
		-- TODO: add constraint!!
		-- Idea: less explicit stereotypes in the profile
		('TYPE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Type').first()})};
														  
-- ensure the use of java primitive types
helper def : javaPrimitiveType : Map(String, UMLMM!Element) = Map{('boolean', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'boolean').first()),
	                                                      		  ('byte', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'byte').first()),
														  		  ('char', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'char').first()),
														  		  ('double', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'double').first()),
														  		  ('float', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'float').first()),
														  		  ('int', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
														  		  ('integer', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),																  
														  		  ('long', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'long').first()),
														  		  ('short', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'short').first()),
																  -- first letter is capital																  
																  ('Boolean', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'boolean').first()),
	                                                      		  ('Byte', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'byte').first()),
														  		  ('Char', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'char').first()),
														  		  ('Double', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'double').first()),
														  		  ('Float', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'float').first()),
														  		  ('Int', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
																  ('Integer', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
														  		  ('Long', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'long').first()),
														  		  ('Short', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'short').first()),
																  -- TODO: maybe we should have here also a Java STRING
																  ('String', UMLMM!Type.allInstancesFrom('UPT') -> select(e | e.name = 'String').first()),
																  -- the array version ...
																  ('boolean[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'boolean').first()),
	                                                      		  ('byte[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'byte').first()),
														  		  ('char[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'char').first()),
														  		  ('double[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'double').first()),
														  		  ('float[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'float').first()),
														  		  ('int[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
														  		  ('long[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'long').first()),
														  		  ('short[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'short').first()),
																  -- TODO: maybe we should have here also a Java STRING
																  ('java.lang.String[]', UMLMM!Type.allInstancesFrom('UPT') -> select(e | e.name = 'String').first())};

-- get package even though types are declared inside types																  
helper context JMM!AbstractTypeDeclaration def : getPackage() : JMM!Package =
	if(not self.package.oclIsUndefined()) then self.package
	-- assumption: the type is declared inside another type
	else self.refImmediateComposite().getPackage()
	endif;
															
	






Back to the top