Commit | Line | Data |
---|---|---|
3a5f73a1 JCK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 Ericsson | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | ******************************************************************************/ | |
6eca054d | 9 | package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model; |
3a5f73a1 JCK |
10 | |
11 | import java.util.ArrayList; | |
12 | import java.util.Arrays; | |
13 | import java.util.Collections; | |
14 | import java.util.HashMap; | |
15 | import java.util.List; | |
16 | import java.util.Map; | |
17 | ||
18 | import org.eclipse.jdt.annotation.NonNull; | |
19 | import org.eclipse.jdt.annotation.Nullable; | |
20 | import org.eclipse.tracecompass.common.core.NonNullUtils; | |
6eca054d GB |
21 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer; |
22 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; | |
3a5f73a1 JCK |
23 | import org.w3c.dom.Element; |
24 | import org.w3c.dom.NodeList; | |
25 | ||
26 | /** | |
27 | * This class implements a state tree described in XML-defined pattern | |
28 | * | |
29 | * @author Jean-Christian Kouame | |
3a5f73a1 JCK |
30 | */ |
31 | public class TmfXmlState { | |
32 | ||
5bf3f444 JCK |
33 | /** The initial state ID */ |
34 | public static final String INITIAL_STATE_ID = "#initial"; //$NON-NLS-1$ | |
3a5f73a1 JCK |
35 | private final String fId; |
36 | private final IXmlStateSystemContainer fContainer; | |
37 | private final List<TmfXmlStateTransition> fTransitions; | |
38 | private @Nullable TmfXmlState fparent; | |
39 | private List<String> fOnEntryActions; | |
40 | private List<String> fOnExitActions; | |
41 | //TODO Sub-state are not yet supported. | |
42 | private Map<String, TmfXmlState> fChildren; | |
43 | private @Nullable TmfXmlStateTransition fInitialTransition; | |
44 | private @Nullable String fInitialStateId; | |
45 | private @Nullable String fFinalStateId; | |
46 | private Type fType; | |
47 | ||
48 | /** | |
49 | * Enum for the type of state | |
50 | */ | |
51 | public enum Type { | |
52 | /** | |
53 | * Final state type | |
54 | */ | |
55 | FINAL, | |
56 | /** | |
57 | * Initial state type | |
58 | */ | |
59 | INITIAL, | |
60 | /** | |
61 | * Fail state type, the pattern has failed to match | |
62 | */ | |
63 | FAIL, | |
64 | /** | |
65 | * This is the normal state type, for states that are not the first, | |
66 | * final or failing state | |
67 | */ | |
68 | DEFAULT | |
69 | } | |
70 | ||
71 | private TmfXmlState(IXmlStateSystemContainer container, Type type, String id, @Nullable TmfXmlState parent, List<@NonNull TmfXmlStateTransition> transitions, Map<@NonNull String, @NonNull TmfXmlState> children, List<String> onentryActions, List<String> onexitActions) { | |
72 | fContainer = container; | |
73 | fType = type; | |
74 | fId = id; | |
75 | fparent = parent; | |
76 | fTransitions = transitions; | |
77 | fChildren = children; | |
78 | fOnEntryActions = onentryActions; | |
79 | fOnExitActions = onexitActions; | |
80 | } | |
81 | ||
82 | /** | |
83 | * Constructor | |
84 | * | |
85 | * @param modelFactory | |
86 | * The factory used to create XML model elements | |
87 | * @param node | |
88 | * The XML root of this state | |
89 | * @param container | |
90 | * The state system container this state definition belongs to | |
91 | * @param parent | |
92 | * The parent state of this state | |
93 | * @return The new {@link TmfXmlState} | |
94 | */ | |
95 | public static TmfXmlState create(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container, @Nullable TmfXmlState parent) { | |
96 | Type type = getStateType(node); | |
97 | String id = node.getAttribute(TmfXmlStrings.ID); | |
98 | List<TmfXmlStateTransition> transitions = getTransitions(modelFactory, container, node); | |
99 | ||
100 | NodeList nodesOnentry = node.getElementsByTagName(TmfXmlStrings.ONENTRY); | |
101 | List<String> onentryActions = nodesOnentry.getLength() > 0 ? Arrays.asList(((Element) nodesOnentry.item(0)).getAttribute(TmfXmlStrings.ACTION).split(TmfXmlStrings.AND_SEPARATOR)) : Collections.EMPTY_LIST; | |
102 | ||
103 | NodeList nodesOnexit = node.getElementsByTagName(TmfXmlStrings.ONEXIT); | |
104 | List<String> onexitActions = nodesOnexit.getLength() > 0 ? Arrays.asList(((Element) nodesOnexit.item(0)).getAttribute(TmfXmlStrings.ACTION).split(TmfXmlStrings.AND_SEPARATOR)) : Collections.EMPTY_LIST; | |
105 | ||
106 | TmfXmlState state = new TmfXmlState(container, type, id, parent, transitions, new HashMap<>(), onentryActions, onexitActions); | |
107 | initState(state, modelFactory, container, node); | |
108 | ||
109 | return state; | |
110 | } | |
111 | ||
112 | private static void getFinalState(TmfXmlState parentState, ITmfXmlModelFactory modelFactory, IXmlStateSystemContainer container, Element node) { | |
113 | NodeList nodesFinal = node.getElementsByTagName(TmfXmlStrings.FINAL); | |
114 | String finalStateId = null; | |
115 | if (nodesFinal.getLength() > 0) { | |
116 | final Element finalElement = NonNullUtils.checkNotNull((Element) nodesFinal.item(0)); | |
117 | finalStateId = nodesFinal.getLength() > 0 ? finalElement.getAttribute(TmfXmlStrings.ID) : null; | |
118 | TmfXmlState finalState = modelFactory.createState(finalElement, container, parentState); | |
119 | parentState.getChildren().put(finalState.getId(), finalState); | |
120 | } | |
121 | parentState.fFinalStateId = finalStateId; | |
122 | } | |
123 | ||
124 | private static void getSubStates(TmfXmlState parentState, ITmfXmlModelFactory modelFactory, IXmlStateSystemContainer container, Element node) { | |
125 | String initial = node.getAttribute(TmfXmlStrings.INITIAL); | |
126 | TmfXmlStateTransition initialTransition = null; | |
127 | if (initial.isEmpty()) { | |
128 | NodeList nodesInitial = node.getElementsByTagName(TmfXmlStrings.INITIAL); | |
129 | if (nodesInitial.getLength() == 1) { | |
130 | final @NonNull Element transitionElement = NonNullUtils.checkNotNull((Element) ((Element) nodesInitial.item(0)).getElementsByTagName(TmfXmlStrings.TRANSITION).item(0)); | |
131 | initialTransition = modelFactory.createStateTransition(transitionElement, container); | |
132 | initial = initialTransition.getTarget(); | |
133 | } | |
134 | } | |
135 | ||
136 | NodeList nodesState = node.getElementsByTagName(TmfXmlStrings.STATE); | |
137 | for (int i = 0; i < nodesState.getLength(); i++) { | |
138 | TmfXmlState child = modelFactory.createState(NonNullUtils.checkNotNull((Element) nodesState.item(i)), container, parentState); | |
139 | parentState.getChildren().put(child.getId(), child); | |
140 | ||
141 | if (i == 0 && initial.isEmpty()) { | |
142 | initial = child.getId(); | |
143 | } | |
144 | } | |
145 | parentState.fInitialStateId = initial.isEmpty() ? null : initial; | |
146 | parentState.fInitialTransition = initialTransition; | |
147 | } | |
148 | ||
149 | private static void initState(TmfXmlState state, ITmfXmlModelFactory modelFactory, IXmlStateSystemContainer container, Element node) { | |
150 | getSubStates(state, modelFactory, container, node); | |
151 | getFinalState(state, modelFactory, container, node); | |
152 | } | |
153 | ||
154 | /** | |
155 | * Get the List of transitions for this state | |
156 | * | |
157 | * @param modelFactory | |
158 | * The factory used to create XML model elements | |
159 | * @param node | |
160 | * The XML root of this state definition | |
161 | * @return The list of transitions | |
162 | */ | |
163 | private static List<@NonNull TmfXmlStateTransition> getTransitions(ITmfXmlModelFactory modelFactory, IXmlStateSystemContainer container, Element node) { | |
164 | List<@NonNull TmfXmlStateTransition> transitions = new ArrayList<>(); | |
165 | NodeList nodesTransition = node.getElementsByTagName(TmfXmlStrings.TRANSITION); | |
166 | for (int i = 0; i < nodesTransition.getLength(); i++) { | |
167 | final Element element = (Element) nodesTransition.item(i); | |
168 | if (element == null) { | |
169 | throw new IllegalArgumentException(); | |
170 | } | |
171 | TmfXmlStateTransition transition = modelFactory.createStateTransition(element, container); | |
172 | transitions.add(transition); | |
173 | } | |
174 | return transitions; | |
175 | } | |
176 | ||
177 | /** | |
178 | * Get the state type from its XML definition | |
179 | * @param node | |
180 | * The XML definition of the state | |
181 | * @return The state type | |
182 | */ | |
183 | private static Type getStateType(Element node) { | |
184 | switch (node.getNodeName()) { | |
185 | case TmfXmlStrings.FINAL: | |
186 | return Type.FINAL; | |
187 | case TmfXmlStrings.INITIAL: | |
188 | return Type.INITIAL; | |
189 | case TmfXmlStrings.ABANDON: | |
190 | return Type.FAIL; | |
191 | case TmfXmlStrings.STATE: | |
192 | default: | |
193 | return Type.DEFAULT; | |
194 | } | |
195 | } | |
196 | ||
197 | /** | |
198 | * Get the state id | |
199 | * | |
200 | * @return The state id | |
201 | */ | |
202 | public String getId() { | |
203 | return fId; | |
204 | } | |
205 | ||
206 | /** | |
207 | * Get the container | |
208 | * | |
209 | * @return The container | |
210 | */ | |
211 | public IXmlStateSystemContainer getContainer() { | |
212 | return fContainer; | |
213 | } | |
214 | ||
215 | /** | |
216 | * The list of transitions of this state | |
217 | * | |
218 | * @return The list of transitions | |
219 | */ | |
220 | public List<TmfXmlStateTransition> getTransitionList() { | |
221 | return fTransitions; | |
222 | } | |
223 | ||
224 | /** | |
225 | * Get the actions to execute when entering this state, in an array | |
226 | * | |
227 | * @return The array of actions | |
228 | */ | |
229 | public List<String> getOnEntryActions() { | |
230 | return fOnEntryActions; | |
231 | } | |
232 | ||
233 | /** | |
234 | * Get the actions to execute when leaving this state, in an array | |
235 | * | |
236 | * @return The array of actions | |
237 | */ | |
238 | public List<String> getOnExitActions() { | |
239 | return fOnExitActions; | |
240 | } | |
241 | ||
242 | /** | |
243 | * Get children states of this state into a map | |
244 | * | |
245 | * @return The map of children state | |
246 | */ | |
247 | public Map<String, TmfXmlState> getChildren() { | |
248 | return fChildren; | |
249 | } | |
250 | ||
251 | /** | |
252 | * Get the initial transition of this state | |
253 | * | |
254 | * @return The initial transition | |
255 | */ | |
256 | public @Nullable TmfXmlStateTransition getInitialTransition() { | |
257 | return fInitialTransition; | |
258 | } | |
259 | ||
260 | /** | |
261 | * Get the initial state ID | |
262 | * | |
263 | * @return The initial state ID | |
264 | */ | |
265 | public @Nullable String getInitialStateId() { | |
266 | return fInitialStateId; | |
267 | } | |
268 | ||
269 | /** | |
270 | * Get the final state ID | |
271 | * | |
272 | * @return The final state ID | |
273 | */ | |
274 | public @Nullable String getFinalStateId() { | |
275 | return fFinalStateId; | |
276 | } | |
277 | ||
278 | /** | |
279 | * Get the parent state | |
280 | * | |
281 | * @return The parent state | |
282 | */ | |
283 | public @Nullable TmfXmlState getParent() { | |
284 | return fparent; | |
285 | } | |
286 | ||
287 | /** | |
288 | * Get the type of this state | |
289 | * | |
290 | * @return The type of the state | |
291 | */ | |
292 | public Type getType() { | |
293 | return fType; | |
294 | } | |
295 | } |