tmf.xml: Bug 500195. Modify initial state behavior
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / internal / tmf / analysis / xml / core / model / TmfXmlState.java
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 ******************************************************************************/
9 package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model;
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;
21 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
22 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
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
30 */
31 public class TmfXmlState {
32
33 /** The initial state ID */
34 public static final String INITIAL_STATE_ID = "#initial"; //$NON-NLS-1$
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 }
This page took 0.037089 seconds and 5 git commands to generate.