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.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 import org.eclipse.etrice.generator.base.logging.ILogger import org.eclipse.etrice.core.genmodel.fsm.IDiagnostician import org.eclipse.etrice.core.room.SubSystemClass import org.eclipse.etrice.core.room.ActorClass @FinalFieldsConstructor class TestInstanceCreator { static val ANNOTATION_TYPE_NAME = "TestInstance" val extension RoomFactory = RoomFactory.eINSTANCE val extension ETMapFactory = ETMapFactory.eINSTANCE // ctor val ILogger logger val IDiagnostician diagnostician /** * Creates instance and mapping for classes having @TestInstance annotation: *

* a) In case of a single SubSystemClass, a new LogicalSystem with a SubSystemRef will be created
* b) For ActorClasses, one new SubSystem- and LogicalSystem with necessary refs will be created
* Resulting ROOM classes are stored in new RoomModel within a new memory-only resource.
* Resulting mapping is stored in a new MappingModel within a new memory-only resource.
*

* * Note: currently only one class having @TestInstance annotation is supported * * @param rs ResourceSet for new resources * @return false, if creation failed and generation should stop */ def List createInstancesAndMapping(Collection 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.roomClasses.filter(SubSystemClass).filter[hasTestAnnotation] return list ]) val List allAnnotatedClasses = newArrayList(allTestSubSystems) // 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.roomClasses.filter(ActorClass).filter[hasTestAnnotation].map[ac| allAnnotatedClasses += ac createActorRef => [ name = "ref_" + ac.name type = ac ]]] if (!derivedSubSystem.actorRefs.isEmpty) allTestSubSystems += derivedSubSystem } if(allTestSubSystems.isEmpty) { return emptyList } // 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| diagnostician.error('''TestInstanceCreator: mapping failed, multiple test instances present''', roomCls, null)] return null } // get physical system val List 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''') 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" roomClasses += testSystem if(testSubSystem.eResource === null) roomClasses += 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) val etmapRes = rs.createResource(uriPath.appendSegment("DerivedTestMappingModel").appendFileExtension("etmap")) etmapRes.contents += testMappingModel val roomRes = rs.createResource(uriPath.appendSegment("DerivedTestRoomModel").appendFileExtension("room")) roomRes.contents += testRoomModel return #[etmapRes, roomRes] } def protected hasTestAnnotation(StructureClass cls) { cls.annotations.exists[type.name == ANNOTATION_TYPE_NAME] } }