1 /*******************************************************************************
2 * Copyright (c) 2016 Ecole Polytechnique de Montreal, 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
.pattern
.stateprovider
.XmlPatternStateProvider
;
23 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
25 import org
.w3c
.dom
.Element
;
26 import org
.w3c
.dom
.NodeList
;
28 import com
.google
.common
.collect
.ImmutableMap
;
31 * This Class implements a pattern handler tree in the XML-defined state system.
32 * It receives events and dispatches it to Active finite state machines.
34 * @author Jean-Christian Kouame
36 public class TmfXmlPatternEventHandler
{
38 /* list of states changes */
39 private final XmlPatternStateProvider fParent
;
41 private final List
<String
> fInitialFsm
;
42 private final Map
<String
, TmfXmlTransitionValidator
> fTestMap
= new HashMap
<>();
43 private final Map
<String
, ITmfXmlAction
> fActionMap
= new HashMap
<>();
44 private final Map
<String
, TmfXmlFsm
> fFsmMap
= new HashMap
<>();
45 private final List
<TmfXmlFsm
> fActiveFsmList
= new ArrayList
<>();
51 * The factory used to create XML model elements
53 * The XML root of this event handler
55 * The state system container this event handler belongs to
57 public TmfXmlPatternEventHandler(ITmfXmlModelFactory modelFactory
, Element node
, IXmlStateSystemContainer parent
) {
58 fParent
= (XmlPatternStateProvider
) parent
;
59 String initialFsm
= node
.getAttribute(TmfXmlStrings
.INITIAL
);
60 fInitialFsm
= initialFsm
.isEmpty() ? Collections
.EMPTY_LIST
: Arrays
.asList(initialFsm
.split(TmfXmlStrings
.AND_SEPARATOR
));
62 NodeList nodesTest
= node
.getElementsByTagName(TmfXmlStrings
.TEST
);
63 /* load transition input */
64 for (int i
= 0; i
< nodesTest
.getLength(); i
++) {
65 Element element
= (Element
) nodesTest
.item(i
);
66 if (element
== null) {
67 throw new IllegalArgumentException();
69 TmfXmlTransitionValidator test
= modelFactory
.createTransitionValidator(element
, fParent
);
70 fTestMap
.put(test
.getId(), test
);
73 NodeList nodesAction
= node
.getElementsByTagName(TmfXmlStrings
.ACTION
);
75 for (int i
= 0; i
< nodesAction
.getLength(); i
++) {
76 Element element
= (Element
) nodesAction
.item(i
);
77 if (element
== null) {
78 throw new IllegalArgumentException();
80 ITmfXmlAction action
= modelFactory
.createAction(element
, fParent
);
81 fActionMap
.put(((TmfXmlAction
) action
).getId(), action
);
83 fActionMap
.put(TmfXmlStrings
.CONSTANT_PREFIX
+ ITmfXmlAction
.CLEAR_STORED_FIELDS_STRING
, new ResetStoredFieldsAction(fParent
));
84 fActionMap
.put(TmfXmlStrings
.CONSTANT_PREFIX
+ ITmfXmlAction
.SAVE_STORED_FIELDS_STRING
, new UpdateStoredFieldsAction(fParent
));
86 NodeList nodesFsm
= node
.getElementsByTagName(TmfXmlStrings
.FSM
);
88 for (int i
= 0; i
< nodesFsm
.getLength(); i
++) {
89 Element element
= (Element
) nodesFsm
.item(i
);
90 if (element
== null) {
91 throw new IllegalArgumentException();
93 TmfXmlFsm fsm
= modelFactory
.createFsm(element
, fParent
);
94 fFsmMap
.put(fsm
.getId(), fsm
);
99 * Start a new scenario for this specific fsm id. If the fsm support only a
100 * single instance and this instance already exist, no new scenario is then
101 * started. If the scenario is created we handle the current event directly.
104 * The IDs of the fsm to start
108 * True to force the creation of the scenario, false otherwise
110 public void startScenario(List
<String
> fsmIds
, @Nullable ITmfEvent event
, boolean force
) {
111 for (String fsmId
: fsmIds
) {
112 TmfXmlFsm fsm
= NonNullUtils
.checkNotNull(fFsmMap
.get(fsmId
));
113 if (!fActiveFsmList
.contains(fsm
)) {
114 fActiveFsmList
.add(fsm
);
116 fsm
.createScenario(event
, this, force
);
121 * Get all the defined transition tests
123 * @return The tests in a map
125 public Map
<String
, TmfXmlTransitionValidator
> getTestMap() {
126 return ImmutableMap
.copyOf(fTestMap
);
130 * Get all the defined actions
132 * @return The actions
134 public Map
<String
, ITmfXmlAction
> getActionMap() {
135 return ImmutableMap
.copyOf(fActionMap
);
139 * If the pattern handler can handle the event, it send the event to all
140 * finite state machines with ongoing scenarios
143 * The trace event to handle
145 public void handleEvent(ITmfEvent event
) {
147 * Order is important so cannot be parallelized
149 final @NonNull List
<@NonNull TmfXmlFsm
> activeFsmList
= fActiveFsmList
;
150 final @NonNull Map
<@NonNull String
, @NonNull TmfXmlFsm
> fsmMap
= fFsmMap
;
151 if (activeFsmList
.isEmpty()) {
152 List
<String
> fsmIds
= fInitialFsm
;
153 if (fsmIds
.isEmpty()) {
154 fsmIds
= new ArrayList
<>();
155 for (TmfXmlFsm fsm
: fsmMap
.values()) {
156 fsmIds
.add(fsm
.getId());
159 if (!fsmIds
.isEmpty()) {
160 startScenario(fsmIds
, null, true);
163 List
<String
> fsmToStart
= new ArrayList
<>();
164 for (Map
.Entry
<String
, TmfXmlFsm
> entry
: fsmMap
.entrySet()) {
165 if (entry
.getValue().isNewScenarioAllowed()) {
166 fsmToStart
.add(entry
.getKey());
169 if (!fsmToStart
.isEmpty()) {
170 startScenario(fsmToStart
, null, false);
173 for (TmfXmlFsm fsm
: activeFsmList
) {
174 fsm
.handleEvent(event
, fTestMap
);
179 * Abandon all the ongoing scenarios
181 public void dispose() {
182 for (TmfXmlFsm fsm
: fActiveFsmList
) {
188 * Get the fsm corresponding to the specified id
192 * @return The fsm found, null if nothing found
194 public @Nullable TmfXmlFsm
getFsm(String fsmId
) {
195 return fFsmMap
.get(fsmId
);