Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 7123acb5ac917c0117f4280e90725eb8d2f1c535 (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
/*******************************************************************************
 * Copyright (c) 2017 protos software gmbh (http://www.protos.de).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * CONTRIBUTORS:
 * 		Henrik Rentz-Reichert (initial contribution)
 * 
 *******************************************************************************/

package org.eclipse.etrice.core.genmodel.fsm

import org.eclipse.etrice.core.fsm.fSM.ChoicepointTerminal
import org.eclipse.etrice.core.fsm.fSM.ModelComponent
import org.eclipse.etrice.core.fsm.fSM.NonInitialTransition
import org.eclipse.etrice.core.fsm.fSM.RefinedState
import org.eclipse.etrice.core.fsm.fSM.RefinedTransition
import org.eclipse.etrice.core.fsm.fSM.SimpleState
import org.eclipse.etrice.core.fsm.fSM.State
import org.eclipse.etrice.core.fsm.fSM.StateGraph
import org.eclipse.etrice.core.fsm.fSM.StateGraphNode
import org.eclipse.etrice.core.fsm.fSM.StateTerminal
import org.eclipse.etrice.core.fsm.fSM.SubStateTrPointTerminal
import org.eclipse.etrice.core.fsm.fSM.TrPointTerminal
import org.eclipse.etrice.core.fsm.fSM.Transition
import org.eclipse.etrice.core.fsm.util.FSMHelpers
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.FsmGenFactory
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.Graph
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.GraphContainer
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.Link
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.Node

class BasicFsmGenBuilder {
	
	protected extension FSMHelpers fsmHelpers
	
	protected val factory = FsmGenFactory.eINSTANCE
	private var int inheritanceLevel = 0
	
	new(FSMHelpers fsmHelpers) {
		this.fsmHelpers = fsmHelpers
	}
	
	def GraphContainer createTransformedModel(ModelComponent mc) {
		mc.createContainer
	}
	
	private def GraphContainer create factory.createGraphContainer createContainer(ModelComponent mc) {
		it.component = mc
		it.graph = createStateMachine(mc)
	}
	
	private def Graph createStateMachine(ModelComponent mc) {
		// neither we nor all of our base classes need to have a state machine.
		// So we ask for the super state machine rather than for the base class'
		// state machine
		val superFSM = mc.superStateMachine
		
		if (superFSM!==null) {
			// if we have a super state machine we first recurse down
			val baseGraph = createStateMachine(superFSM.modelComponent)
			
			// when we ascend from the recursion we increment the inheritanceLevel
			inheritanceLevel++
			
			// and then merge with our (actual) state machine
			mergeGraph(baseGraph, mc.actualStateMachine)
		}
		else if (mc.actualStateMachine!==null) {
			// first state machine in the hierarchy: create it
			mc.actualStateMachine?.createGraph
		}
	}
	
	private def Graph mergeGraph(Graph graph, StateGraph sg) {
		// mark existing items as inherited
		graph.nodes.forEach[inherited = true]
		graph.links.forEach[inherited = true]
		
		// add items to already existing graph
		graph.createContents(sg)
		
		// point to the current state graph
		graph.stateGraph = sg
		
		return graph
	}
	
	private def Graph create factory.createGraph createGraph(StateGraph sg) {
		it.stateGraph = sg
		createContents(sg)
	}
	
	private def createContents(Graph graph, StateGraph sg) {
		graph.nodes.addAll(sg.chPoints.map[createNode])
		graph.nodes.addAll(sg.trPoints.map[createNode])
		graph.nodes.addAll(sg.states.filter(typeof(SimpleState)).map[createNode])
		graph.links.addAll(sg.transitions.map[createLink])
		
		// refined states and refined transitions
		sg.states.filter(typeof(RefinedState)).forEach[handleRefinedState]
		sg.refinedTransitions.forEach[handleRefinedTransition]
	}
	
	private def handleRefinedState(RefinedState s) {
		// we pick the node that initially was created from a SimpleState
		val refinedNode = s.finalTarget.createNode
		
		// handle the sub graphs
		if (s.subgraph!==null) {
			if (refinedNode.subgraph!==null) {
				refinedNode.subgraph.mergeGraph(s.subgraph)
			}
			else {
				refinedNode.subgraph = s.subgraph.createGraph
			}
		}
		// else nothing to do, whether the targetGraph exists or not
		
		// change the target Node's stateGraphNode to our RefinedState
		val target = refinedNode
		target.stateGraphNode = s
	}
	
	private def handleRefinedTransition(RefinedTransition t) {
		// change the target link's transition to the refined transition
		t.target.createLink.transition = t
	}
	
	private def Link create factory.createLink createLink(Transition tr) {
		it.transition = tr
		it.source = if (tr instanceof NonInitialTransition) tr.from.createNode
		it.target = tr.to.createNode
	}
	
	private def dispatch create factory.createNode createNode(StateGraphNode s) {
		it.stateGraphNode = s
		it.inheritanceLevel = inheritanceLevel
		it.subgraph = if(s instanceof State) s.subgraph?.createGraph
	}
	
	private def dispatch Node createNode(ChoicepointTerminal tt) {
		tt.cp.createNode
	}
	
	private def dispatch Node createNode(TrPointTerminal tt) {
		tt.trPoint.createNode
	}
	
	private def dispatch Node createNode(StateTerminal tt) {
		tt.state.createNode
	}
	
	private def dispatch Node createNode(SubStateTrPointTerminal tt) {
		tt.trPoint.createNode
	}
}

Back to the top