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
|
package org.eclipse.etrice.generator.generic
import java.util.List
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.etrice.core.etmap.eTMap.ETMapFactory
import org.eclipse.etrice.core.etphys.eTPhys.PhysicalModel
import org.eclipse.etrice.core.etphys.eTPhys.PhysicalSystem
import org.eclipse.etrice.core.genmodel.fsm.ILogger
import org.eclipse.etrice.core.room.RoomFactory
import org.eclipse.etrice.core.room.RoomModel
import org.eclipse.etrice.core.room.StructureClass
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
import java.util.Collection
import org.eclipse.emf.common.util.URI
@FinalFieldsConstructor
class TestInstanceCreator {
static val ANNOTATION_TYPE_NAME = "TestInstance"
val extension RoomFactory = RoomFactory.eINSTANCE
val extension ETMapFactory = ETMapFactory.eINSTANCE
// ctor
val ILogger logger
/**
* Creates instance and mapping for classes having <code>@TestInstance</code> annotation:
* <p>
* a) In case of a single SubSystemClass, a new LogicalSystem with a SubSystemRef will be created<br>
* b) For ActorClasses, one new SubSystem- and LogicalSystem with necessary refs will be created</br>
* Resulting ROOM classes are stored in new RoomModel within a new memory-only resource.</br>
* Resulting mapping is stored in a new MappingModel within a new memory-only resource.</br>
* </p>
*
* Note: currently only one class having <code>@TestInstance</code> annotation is supported
*
* @param rs ResourceSet for new resources
* @return false, if creation failed and generation should stop
*/
def List<Resource> createInstancesAndMapping(Collection<URI> modelsURIs, ResourceSet rs) {
val roomModels = newArrayList
val physModels = newArrayList
rs.resources.forEach[contents.forEach[switch it {
RoomModel: if(modelsURIs.contains(eResource.URI)) roomModels += it
PhysicalModel: physModels += it
}]]
// try find annotated SubSystemClass
val allTestSubSystems = roomModels.fold(newArrayList, [list, model |
list += model.subSystemClasses.filter[hasTestAnnotation] return list
])
val List<StructureClass> allAnnotatedClasses = newArrayList(allTestSubSystems)
val result = newArrayList
// try find annotated ActorClasses and map them to virtual sub system
{
val derivedSubSystem = createSubSystemClass => [name = "DerivedTestSubSystem"]
roomModels.forEach[model|
// actors to actorRef into subsystem
derivedSubSystem.actorRefs += model.actorClasses.filter[hasTestAnnotation].map[ac|
allAnnotatedClasses += ac
createActorRef => [
name = "ref_" + ac.name
type = ac
]]]
if (!derivedSubSystem.actorRefs.isEmpty)
allTestSubSystems += derivedSubSystem
}
if(allTestSubSystems.isEmpty) {
return result
}
// if (roomModels.exists[model|!model.systems.empty]) {
// allAnnotatedClasses.forEach[roomCls|
// logger.logInfo(
// '''TestInstanceCreator: ignored annotation '@«ANNOTATION_TYPE_NAME»' at «roomCls.name»:«roomCls.eClass.name», because there is already a LogicalSystem («roomCls.eResource.URI»)''')]
// return true
// }
// validation
if (allAnnotatedClasses.size > 1) {
allAnnotatedClasses.forEach[roomCls|
logger.logError('''TestInstanceCreator: mapping failed, multiple test instances present''', roomCls)]
return null
}
// get physical system
val List<PhysicalSystem> allPhysSystems = physModels.fold(newArrayList,[list, model|list += model.systems return list])
if (allPhysSystems.size != 1) {
logger.logError('''TestInstanceCreator: mapping failed, found «allPhysSystems.size» physical systems''', null)
return null
}
// create mapping
logger.logInfo('''TestInstanceCreator: creating instance and mapping for «allAnnotatedClasses.head.name»:«allAnnotatedClasses.head.eClass.name»''')
val physSystem = allPhysSystems.head
val testSubSystem = allTestSubSystems.head
val testSystem = createLogicalSystem => [name = "DerivedTestSystem"]
testSystem.subSystems += createSubSystemRef => [name = "ref_" + testSubSystem.name type = testSubSystem]
val testRoomModel = createRoomModel => [
name = "DerivedTestRoomModel"
systems += testSystem
if(testSubSystem.eResource === null) subSystemClasses += testSubSystem
]
val testMappingModel = createMappingModel => [
name = "DerivedTestMappingModel"
mappings += createMapping => [
logicalSys = testSystem
physicalSys = physSystem
subsysMappings += testSystem.subSystems.map [ subSysRef |
createSubSystemMapping => [
logicalSubSys = subSysRef
node = physSystem.nodeRefs.head
]
]
]
]
// create memory resource with same uri locations as test instance
val Resource existingResource = if(testSubSystem.eResource !== null) testSubSystem.eResource else allAnnotatedClasses.head.eResource
val uriPath = existingResource.URI.trimFileExtension.trimSegments(1)
var res = rs.createResource(uriPath.appendSegment("DerivedTestMappingModel").appendFileExtension("etmap"))
res.contents += testMappingModel
result.add(res)
res = rs.createResource(uriPath.appendSegment("DerivedTestRoomModel").appendFileExtension("room"))
res.contents += testRoomModel
result.add(res)
return result
}
def protected hasTestAnnotation(StructureClass cls) {
cls.annotations.exists[type.name == ANNOTATION_TYPE_NAME]
}
}
|