99b8ac9ac6f7cbb2e9fd23b2731b1d34afd52159
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / internal / tmf / analysis / xml / core / model / TmfXmlPatternEventHandler.java
1 /*******************************************************************************
2 * Copyright (c) 2016 Ecole Polytechnique de Montreal, 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.LinkedHashMap;
16 import java.util.List;
17 import java.util.Map;
18
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.tracecompass.common.core.NonNullUtils;
22 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
23 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternStateProvider;
24 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
25 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
26 import org.w3c.dom.Element;
27 import org.w3c.dom.NodeList;
28
29 import com.google.common.collect.ImmutableMap;
30 import com.google.common.collect.ImmutableMap.Builder;
31
32 /**
33 * This Class implements a pattern handler tree in the XML-defined state system.
34 * It receives events and dispatches it to Active finite state machines.
35 *
36 * @author Jean-Christian Kouame
37 */
38 public class TmfXmlPatternEventHandler {
39
40 /* list of states changes */
41 private final XmlPatternStateProvider fParent;
42
43 private final List<String> fInitialFsm;
44 private final Map<String, TmfXmlTransitionValidator> fTestMap;
45 private final Map<String, ITmfXmlAction> fActionMap;
46 private final Map<String, TmfXmlFsm> fFsmMap = new LinkedHashMap<>();
47 private final List<TmfXmlFsm> fActiveFsmList = new ArrayList<>();
48
49 /**
50 * Constructor
51 *
52 * @param modelFactory
53 * The factory used to create XML model elements
54 * @param node
55 * The XML root of this event handler
56 * @param parent
57 * The state system container this event handler belongs to
58 */
59 public TmfXmlPatternEventHandler(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer parent) {
60 fParent = (XmlPatternStateProvider) parent;
61 String initialFsm = node.getAttribute(TmfXmlStrings.INITIAL);
62 fInitialFsm = initialFsm.isEmpty() ? Collections.EMPTY_LIST : Arrays.asList(initialFsm.split(TmfXmlStrings.AND_SEPARATOR));
63
64 Map<String, TmfXmlTransitionValidator> testMap = new HashMap<>();
65 NodeList nodesTest = node.getElementsByTagName(TmfXmlStrings.TEST);
66 /* load transition input */
67 for (int i = 0; i < nodesTest.getLength(); i++) {
68 Element element = (Element) nodesTest.item(i);
69 if (element == null) {
70 throw new IllegalArgumentException();
71 }
72 TmfXmlTransitionValidator test = modelFactory.createTransitionValidator(element, fParent);
73 testMap.put(test.getId(), test);
74 }
75 fTestMap = Collections.unmodifiableMap(testMap);
76
77 @NonNull Builder<String, ITmfXmlAction> builder = ImmutableMap.builder();
78 NodeList nodesAction = node.getElementsByTagName(TmfXmlStrings.ACTION);
79 /* load actions */
80 for (int i = 0; i < nodesAction.getLength(); i++) {
81 Element element = (Element) nodesAction.item(i);
82 if (element == null) {
83 throw new IllegalArgumentException();
84 }
85 TmfXmlAction action = modelFactory.createAction(element, fParent);
86 builder.put(action.getId(), action);
87 }
88 builder.put(TmfXmlStrings.CONSTANT_PREFIX + ITmfXmlAction.CLEAR_STORED_FIELDS_STRING, new ResetStoredFieldsAction(fParent));
89 builder.put(TmfXmlStrings.CONSTANT_PREFIX + ITmfXmlAction.SAVE_STORED_FIELDS_STRING, new UpdateStoredFieldsAction(fParent));
90 fActionMap = builder.build();
91
92 NodeList nodesFsm = node.getElementsByTagName(TmfXmlStrings.FSM);
93 /* load fsm */
94 for (int i = 0; i < nodesFsm.getLength(); i++) {
95 Element element = (Element) nodesFsm.item(i);
96 if (element == null) {
97 throw new IllegalArgumentException();
98 }
99 TmfXmlFsm fsm = modelFactory.createFsm(element, fParent);
100 fFsmMap.put(fsm.getId(), fsm);
101 }
102 }
103
104 /**
105 * Start a new scenario for this specific fsm id. If the fsm support only a
106 * single instance and this instance already exist, no new scenario is then
107 * started. If the scenario is created we handle the current event directly.
108 *
109 * @param fsmIds
110 * The IDs of the fsm to start
111 * @param event
112 * The current event
113 * @param force
114 * True to force the creation of the scenario, false otherwise
115 */
116 public void startScenario(List<String> fsmIds, @Nullable ITmfEvent event, boolean force) {
117 for (String fsmId : fsmIds) {
118 TmfXmlFsm fsm = NonNullUtils.checkNotNull(fFsmMap.get(fsmId));
119 if (!fActiveFsmList.contains(fsm)) {
120 fActiveFsmList.add(fsm);
121 }
122 fsm.createScenario(event, this, force);
123 }
124 }
125
126 /**
127 * Get all the defined transition tests
128 *
129 * @return The tests in a map
130 */
131 public Map<String, TmfXmlTransitionValidator> getTestMap() {
132 return fTestMap;
133 }
134
135 /**
136 * Get all the defined actions
137 *
138 * @return The actions
139 */
140 public Map<String, ITmfXmlAction> getActionMap() {
141 return fActionMap;
142 }
143
144 /**
145 * If the pattern handler can handle the event, it send the event to all
146 * finite state machines with ongoing scenarios
147 *
148 * @param event
149 * The trace event to handle
150 */
151 public void handleEvent(ITmfEvent event) {
152 /*
153 * Order is important so cannot be parallelized
154 */
155 final @NonNull List<@NonNull TmfXmlFsm> activeFsmList = fActiveFsmList;
156 final @NonNull Map<@NonNull String, @NonNull TmfXmlFsm> fsmMap = fFsmMap;
157 if (activeFsmList.isEmpty()) {
158 List<String> fsmIds = fInitialFsm;
159 if (fsmIds.isEmpty()) {
160 fsmIds = new ArrayList<>();
161 for (TmfXmlFsm fsm : fsmMap.values()) {
162 fsmIds.add(fsm.getId());
163 }
164 }
165 if (!fsmIds.isEmpty()) {
166 startScenario(fsmIds, null, true);
167 }
168 } else {
169 List<String> fsmToStart = new ArrayList<>();
170 for (Map.Entry<String, TmfXmlFsm> entry : fsmMap.entrySet()) {
171 if (entry.getValue().isNewScenarioAllowed()) {
172 fsmToStart.add(entry.getKey());
173 }
174 }
175 if (!fsmToStart.isEmpty()) {
176 startScenario(fsmToStart, null, false);
177 }
178 }
179 for (TmfXmlFsm fsm : activeFsmList) {
180 fsm.handleEvent(event, fTestMap);
181 }
182 }
183
184 /**
185 * Abandon all the ongoing scenarios
186 */
187 public void dispose() {
188 for (TmfXmlFsm fsm : fActiveFsmList) {
189 fsm.dispose();
190 }
191 }
192
193 /**
194 * Get the fsm corresponding to the specified id
195 *
196 * @param fsmId
197 * The id of the fsm
198 * @return The fsm found, null if nothing found
199 */
200 public @Nullable TmfXmlFsm getFsm(String fsmId) {
201 return fFsmMap.get(fsmId);
202 }
203 }
This page took 0.036156 seconds and 5 git commands to generate.