Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: e03c73343675523e249b045b3f0accba7afa8577 (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
/*******************************************************************************
 * 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 com.google.inject.Inject
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.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.fsm.fSM.State
import org.eclipse.etrice.core.fsm.fSM.RefinedState
import org.eclipse.etrice.core.fsm.fSM.SimpleState
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.Node
import com.google.inject.Injector
import org.eclipse.etrice.core.fsm.fSM.RefinedTransition

class FsmGenBuilder {
	
	@Inject extension FSMHelpers fsmHelpers
	val factory = FsmGenFactory.eINSTANCE
	
	new(Injector injector) {
		injector.injectMembers(this)
	}
	
	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)
			
			// and then merge with our (actual) state machine
			mergeGraph(baseGraph, mc.actualStateMachine)
		}
		else {
			// 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 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 transitions
		sg.states.filter(typeof(RefinedState)).forEach[handleRefinedState]
		sg.refinedTransitions.forEach[handleRefinedTransition]
	}
	
	private def handleRefinedState(RefinedState s) {
		// handle the sub graphs
		if (s.subgraph!=null) {
			if (s.target.subgraph!=null) {
				val targetGraph = s.target.subgraph.createGraph
				targetGraph.mergeGraph(s.subgraph)
			}
			else {
				s.target.createNode.subgraph = s.subgraph.createGraph
			}
		}
		// else nothing to do, whether the targetGraph exist or not
		
		// change the target Node's stateGraphNode to our RefinedState
		val target = s.target.createNode
		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 create factory.createLink createLink(Transition tr) {
		it.transition = tr
		
		it.source = if (tr instanceof NonInitialTransition)  {
			tr.from.createNode
		}
		else {
			null
		}
		it.target = tr.to.createNode
	}
	
	private def dispatch create factory.createNode createNode(StateGraphNode s) {
		it.stateGraphNode = s

		it.subgraph = 
			if (s instanceof State && (s as State).subgraph!=null) {
				(s as State).subgraph.createGraph
			}
			else null
	}
	
	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