blob: 11fdbab58d95c8de424ee466aed1425597e7708d [file] [log] [blame]
/**
* *******************************************************************************
* Copyright (c) 2019 Robert Bosch GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Robert Bosch GmbH - initial API and implementation
* *******************************************************************************
*/
package templates.m2m.constraints
import com.google.inject.Inject
import com.google.inject.Singleton
import com.inchron.realtime.root.model.DataFlow
import com.inchron.realtime.root.model.DataFlowEdge
import org.eclipse.app4mc.amalthea.model.AbstractEventChain
import org.eclipse.app4mc.amalthea.model.ChannelAccess
import org.eclipse.app4mc.amalthea.model.ChannelEvent
import org.eclipse.app4mc.amalthea.model.EventChain
import org.eclipse.app4mc.amalthea.model.EventChainContainer
import org.eclipse.app4mc.amalthea.model.EventChainItem
import org.eclipse.app4mc.amalthea.model.EventChainReference
import org.eclipse.app4mc.amalthea.model.Process
import templates.AbstractAmaltheaInchronTransformer
import templates.m2m.sw.runnableItem.ChannelAccessTransformer
import templates.m2m.utils.DataFlowUtils
@Singleton
class EventChainTransformer extends AbstractAmaltheaInchronTransformer {
@Inject EventChainReferenceTransformer eventChainReferenceTransformer
@Inject ChannelAccessTransformer channelAccessTransformer
def create inchronModelFactory.createDataFlow createDataFlow(EventChain amltEventChain) {
//check if amalthea structure is feasible to be transformed to data flow
//list of checks:
// - no circular dependencies within nested event chain references
// - channel event specifies: runnable, channel, access type (send or receive)
// - stimulus and response are of type channel event
// - stimulus and responsecan be traced to ONE specific channel access runnable item
// - rules above also apply to nested and referenced event chains
// Note: strands are not supported and will be neglected
if (DataFlowUtils.isDataFlow(amltEventChain)){
it.name = amltEventChain.name
extendDataFlow(it, amltEventChain)
getInchronRoot.eventChains.add(it)
} else {
//do event sequence sequence
getLogger.error("Event chain " + amltEventChain.name + " cannot be converted, as it is not a feasible data flow")
}
}
def void extendDataFlow(DataFlow dataFlow, AbstractEventChain amltAbstractEventChain) {
if (!amltAbstractEventChain.segments.isEmpty) {
//event chain is hierarchical --> step down
amltAbstractEventChain.segments.forEach[EventChainItem amltEventChainItem | { //item may be a container or a reference
if (amltEventChainItem instanceof EventChainContainer){
//recursively process contained (sub)event chain
extendDataFlow(dataFlow, (amltEventChainItem as EventChainContainer).eventChain)
} else if (amltEventChainItem instanceof EventChainReference) {
//create [cs]DataFlowReference from [amlt]EventChainReference
dataFlow.references.add(eventChainReferenceTransformer.createDataFlowReference(
(amltEventChainItem as EventChainReference), amltAbstractEventChain))
}
}]
}
else {
//create new edge
val DataFlowEdge dataFlowEdge = inchronModelFactory.createDataFlowEdge
//set stimulus and receiver according to channel events
val Process stimulusTask = (amltAbstractEventChain.stimulus as ChannelEvent).process
val ChannelAccess stimulus = DataFlowUtils.findChannelAccess(amltAbstractEventChain.stimulus as ChannelEvent)
if (stimulus !== null){
dataFlowEdge.stimulus = channelAccessTransformer.createVariableAccess(stimulusTask, stimulus)
} else {
dataFlowEdge.stimulus = null;
}
val Process responseTask = (amltAbstractEventChain.response as ChannelEvent).process
val ChannelAccess response = DataFlowUtils.findChannelAccess(amltAbstractEventChain.response as ChannelEvent)
if (response !== null){
dataFlowEdge.response = channelAccessTransformer.createVariableAccess(responseTask, response)
} else {
dataFlowEdge.response = null;
}
//add new edge dataflow
dataFlow.edges.add(dataFlowEdge)
}
}
}