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