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
.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
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
22 import org
.eclipse
.tracecompass
.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
32 public class TmfXmlState
{
34 private final String fId
;
35 private final IXmlStateSystemContainer fContainer
;
36 private final List
<TmfXmlStateTransition
> fTransitions
;
37 private @Nullable TmfXmlState fparent
;
38 private List
<String
> fOnEntryActions
;
39 private List
<String
> fOnExitActions
;
40 //TODO Sub-state are not yet supported.
41 private Map
<String
, TmfXmlState
> fChildren
;
42 private @Nullable TmfXmlStateTransition fInitialTransition
;
43 private @Nullable String fInitialStateId
;
44 private @Nullable String fFinalStateId
;
48 * Enum for the type of state
60 * Fail state type, the pattern has failed to match
64 * This is the normal state type, for states that are not the first,
65 * final or failing state
70 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
) {
71 fContainer
= container
;
75 fTransitions
= transitions
;
77 fOnEntryActions
= onentryActions
;
78 fOnExitActions
= onexitActions
;
85 * The factory used to create XML model elements
87 * The XML root of this state
89 * The state system container this state definition belongs to
91 * The parent state of this state
92 * @return The new {@link TmfXmlState}
94 public static TmfXmlState
create(ITmfXmlModelFactory modelFactory
, Element node
, IXmlStateSystemContainer container
, @Nullable TmfXmlState parent
) {
95 Type type
= getStateType(node
);
96 String id
= node
.getAttribute(TmfXmlStrings
.ID
);
97 List
<TmfXmlStateTransition
> transitions
= getTransitions(modelFactory
, container
, node
);
99 NodeList nodesOnentry
= node
.getElementsByTagName(TmfXmlStrings
.ONENTRY
);
100 List
<String
> onentryActions
= nodesOnentry
.getLength() > 0 ? Arrays
.asList(((Element
) nodesOnentry
.item(0)).getAttribute(TmfXmlStrings
.ACTION
).split(TmfXmlStrings
.AND_SEPARATOR
)) : Collections
.EMPTY_LIST
;
102 NodeList nodesOnexit
= node
.getElementsByTagName(TmfXmlStrings
.ONEXIT
);
103 List
<String
> onexitActions
= nodesOnexit
.getLength() > 0 ? Arrays
.asList(((Element
) nodesOnexit
.item(0)).getAttribute(TmfXmlStrings
.ACTION
).split(TmfXmlStrings
.AND_SEPARATOR
)) : Collections
.EMPTY_LIST
;
105 TmfXmlState state
= new TmfXmlState(container
, type
, id
, parent
, transitions
, new HashMap
<>(), onentryActions
, onexitActions
);
106 initState(state
, modelFactory
, container
, node
);
111 private static void getFinalState(TmfXmlState parentState
, ITmfXmlModelFactory modelFactory
, IXmlStateSystemContainer container
, Element node
) {
112 NodeList nodesFinal
= node
.getElementsByTagName(TmfXmlStrings
.FINAL
);
113 String finalStateId
= null;
114 if (nodesFinal
.getLength() > 0) {
115 final Element finalElement
= NonNullUtils
.checkNotNull((Element
) nodesFinal
.item(0));
116 finalStateId
= nodesFinal
.getLength() > 0 ? finalElement
.getAttribute(TmfXmlStrings
.ID
) : null;
117 TmfXmlState finalState
= modelFactory
.createState(finalElement
, container
, parentState
);
118 parentState
.getChildren().put(finalState
.getId(), finalState
);
120 parentState
.fFinalStateId
= finalStateId
;
123 private static void getSubStates(TmfXmlState parentState
, ITmfXmlModelFactory modelFactory
, IXmlStateSystemContainer container
, Element node
) {
124 String initial
= node
.getAttribute(TmfXmlStrings
.INITIAL
);
125 TmfXmlStateTransition initialTransition
= null;
126 if (initial
.isEmpty()) {
127 NodeList nodesInitial
= node
.getElementsByTagName(TmfXmlStrings
.INITIAL
);
128 if (nodesInitial
.getLength() == 1) {
129 final @NonNull Element transitionElement
= NonNullUtils
.checkNotNull((Element
) ((Element
) nodesInitial
.item(0)).getElementsByTagName(TmfXmlStrings
.TRANSITION
).item(0));
130 initialTransition
= modelFactory
.createStateTransition(transitionElement
, container
);
131 initial
= initialTransition
.getTarget();
135 NodeList nodesState
= node
.getElementsByTagName(TmfXmlStrings
.STATE
);
136 for (int i
= 0; i
< nodesState
.getLength(); i
++) {
137 TmfXmlState child
= modelFactory
.createState(NonNullUtils
.checkNotNull((Element
) nodesState
.item(i
)), container
, parentState
);
138 parentState
.getChildren().put(child
.getId(), child
);
140 if (i
== 0 && initial
.isEmpty()) {
141 initial
= child
.getId();
144 parentState
.fInitialStateId
= initial
.isEmpty() ?
null : initial
;
145 parentState
.fInitialTransition
= initialTransition
;
148 private static void initState(TmfXmlState state
, ITmfXmlModelFactory modelFactory
, IXmlStateSystemContainer container
, Element node
) {
149 getSubStates(state
, modelFactory
, container
, node
);
150 getFinalState(state
, modelFactory
, container
, node
);
154 * Get the List of transitions for this state
156 * @param modelFactory
157 * The factory used to create XML model elements
159 * The XML root of this state definition
160 * @return The list of transitions
162 private static List
<@NonNull TmfXmlStateTransition
> getTransitions(ITmfXmlModelFactory modelFactory
, IXmlStateSystemContainer container
, Element node
) {
163 List
<@NonNull TmfXmlStateTransition
> transitions
= new ArrayList
<>();
164 NodeList nodesTransition
= node
.getElementsByTagName(TmfXmlStrings
.TRANSITION
);
165 for (int i
= 0; i
< nodesTransition
.getLength(); i
++) {
166 final Element element
= (Element
) nodesTransition
.item(i
);
167 if (element
== null) {
168 throw new IllegalArgumentException();
170 TmfXmlStateTransition transition
= modelFactory
.createStateTransition(element
, container
);
171 transitions
.add(transition
);
177 * Get the state type from its XML definition
179 * The XML definition of the state
180 * @return The state type
182 private static Type
getStateType(Element node
) {
183 switch (node
.getNodeName()) {
184 case TmfXmlStrings
.FINAL
:
186 case TmfXmlStrings
.INITIAL
:
188 case TmfXmlStrings
.ABANDON
:
190 case TmfXmlStrings
.STATE
:
199 * @return The state id
201 public String
getId() {
208 * @return The container
210 public IXmlStateSystemContainer
getContainer() {
215 * The list of transitions of this state
217 * @return The list of transitions
219 public List
<TmfXmlStateTransition
> getTransitionList() {
224 * Get the actions to execute when entering this state, in an array
226 * @return The array of actions
228 public List
<String
> getOnEntryActions() {
229 return fOnEntryActions
;
233 * Get the actions to execute when leaving this state, in an array
235 * @return The array of actions
237 public List
<String
> getOnExitActions() {
238 return fOnExitActions
;
242 * Get children states of this state into a map
244 * @return The map of children state
246 public Map
<String
, TmfXmlState
> getChildren() {
251 * Get the initial transition of this state
253 * @return The initial transition
255 public @Nullable TmfXmlStateTransition
getInitialTransition() {
256 return fInitialTransition
;
260 * Get the initial state ID
262 * @return The initial state ID
264 public @Nullable String
getInitialStateId() {
265 return fInitialStateId
;
269 * Get the final state ID
271 * @return The final state ID
273 public @Nullable String
getFinalStateId() {
274 return fFinalStateId
;
278 * Get the parent state
280 * @return The parent state
282 public @Nullable TmfXmlState
getParent() {
287 * Get the type of this state
289 * @return The type of the state
291 public Type
getType() {