1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
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
;
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
;
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
;
27 * This class implements a state tree described in XML-defined pattern
29 * @author Jean-Christian Kouame
31 public class TmfXmlState
{
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
;
49 * Enum for the type of state
61 * Fail state type, the pattern has failed to match
65 * This is the normal state type, for states that are not the first,
66 * final or failing state
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
;
76 fTransitions
= transitions
;
78 fOnEntryActions
= onentryActions
;
79 fOnExitActions
= onexitActions
;
86 * The factory used to create XML model elements
88 * The XML root of this state
90 * The state system container this state definition belongs to
92 * The parent state of this state
93 * @return The new {@link TmfXmlState}
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
);
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
;
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
;
106 TmfXmlState state
= new TmfXmlState(container
, type
, id
, parent
, transitions
, new HashMap
<>(), onentryActions
, onexitActions
);
107 initState(state
, modelFactory
, container
, node
);
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
);
121 parentState
.fFinalStateId
= finalStateId
;
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();
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
);
141 if (i
== 0 && initial
.isEmpty()) {
142 initial
= child
.getId();
145 parentState
.fInitialStateId
= initial
.isEmpty() ?
null : initial
;
146 parentState
.fInitialTransition
= initialTransition
;
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
);
155 * Get the List of transitions for this state
157 * @param modelFactory
158 * The factory used to create XML model elements
160 * The XML root of this state definition
161 * @return The list of transitions
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();
171 TmfXmlStateTransition transition
= modelFactory
.createStateTransition(element
, container
);
172 transitions
.add(transition
);
178 * Get the state type from its XML definition
180 * The XML definition of the state
181 * @return The state type
183 private static Type
getStateType(Element node
) {
184 switch (node
.getNodeName()) {
185 case TmfXmlStrings
.FINAL
:
187 case TmfXmlStrings
.INITIAL
:
189 case TmfXmlStrings
.ABANDON
:
191 case TmfXmlStrings
.STATE
:
200 * @return The state id
202 public String
getId() {
209 * @return The container
211 public IXmlStateSystemContainer
getContainer() {
216 * The list of transitions of this state
218 * @return The list of transitions
220 public List
<TmfXmlStateTransition
> getTransitionList() {
225 * Get the actions to execute when entering this state, in an array
227 * @return The array of actions
229 public List
<String
> getOnEntryActions() {
230 return fOnEntryActions
;
234 * Get the actions to execute when leaving this state, in an array
236 * @return The array of actions
238 public List
<String
> getOnExitActions() {
239 return fOnExitActions
;
243 * Get children states of this state into a map
245 * @return The map of children state
247 public Map
<String
, TmfXmlState
> getChildren() {
252 * Get the initial transition of this state
254 * @return The initial transition
256 public @Nullable TmfXmlStateTransition
getInitialTransition() {
257 return fInitialTransition
;
261 * Get the initial state ID
263 * @return The initial state ID
265 public @Nullable String
getInitialStateId() {
266 return fInitialStateId
;
270 * Get the final state ID
272 * @return The final state ID
274 public @Nullable String
getFinalStateId() {
275 return fFinalStateId
;
279 * Get the parent state
281 * @return The parent state
283 public @Nullable TmfXmlState
getParent() {
288 * Get the type of this state
290 * @return The type of the state
292 public Type
getType() {