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 / TmfXmlStateAttribute.java
CommitLineData
0f7276b6 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2014, 2015 Ecole Polytechnique de Montreal
0f7276b6
GB
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 * Contributors:
10 * Florian Wininger - Initial API and implementation
11 ******************************************************************************/
12
2bdf0193 13package org.eclipse.tracecompass.tmf.analysis.xml.core.model;
0f7276b6 14
1d7e62f9 15import java.util.LinkedList;
0f7276b6
GB
16import java.util.List;
17
1d7e62f9 18import org.eclipse.jdt.annotation.Nullable;
0b563c20
JCK
19import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
20import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
21
2bdf0193 22import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
e894a508
AM
23import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
24import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
25import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
26import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
27import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
28import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
2bdf0193
AM
29import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
30import org.eclipse.tracecompass.tmf.analysis.xml.core.module.XmlUtils;
31import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
32import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
33import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
35f39420
AM
34import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
35import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
0f7276b6
GB
36import org.w3c.dom.Element;
37
38/**
1d7e62f9
GB
39 * This Class implements a single attribute value in the XML-defined state
40 * system.
0f7276b6
GB
41 *
42 * <pre>
43 * Examples:
44 * <stateAttribute type="constant" value="Threads" />
45 * <stateAttribute type="query" />
46 * <stateAttribute type="constant" value="CPUs" />
47 * <stateAttribute type="eventField" value="cpu" />
48 * <stateAttribute type="constant" value="Current_thread" />
49 * </attribute>
50 * </pre>
51 *
52 * @author Florian Wininger
53 */
1d7e62f9 54public abstract class TmfXmlStateAttribute implements ITmfXmlStateAttribute {
0f7276b6
GB
55
56 private enum StateAttributeType {
57 NONE,
58 CONSTANT,
59 EVENTFIELD,
60 QUERY,
1d7e62f9 61 LOCATION,
597168fc
NE
62 SELF,
63 EVENTNAME
0f7276b6
GB
64 }
65
0b563c20
JCK
66 private final String CURRENT_STATE = "#currentState"; //$NON-NLS-1$
67
3a5f73a1
JCK
68 private final String CURRENT_SCENARIO = "#CurrentScenario"; //$NON-NLS-1$
69
0f7276b6
GB
70 /** Type of attribute */
71 private final StateAttributeType fType;
72
73 /** Attribute's name */
12685851 74 private final @Nullable String fName;
0f7276b6
GB
75
76 /** List of attributes for a query */
1d7e62f9 77 private final List<ITmfXmlStateAttribute> fQueryList = new LinkedList<>();
0f7276b6 78
1d7e62f9 79 private final IXmlStateSystemContainer fContainer;
0f7276b6
GB
80
81 /**
82 * Constructor
83 *
1d7e62f9
GB
84 * @param modelFactory
85 * The factory used to create XML model elements
0f7276b6
GB
86 * @param attribute
87 * XML element of the attribute
1d7e62f9
GB
88 * @param container
89 * The state system container this state attribute belongs to
0f7276b6 90 */
1d7e62f9
GB
91 protected TmfXmlStateAttribute(ITmfXmlModelFactory modelFactory, Element attribute, IXmlStateSystemContainer container) {
92 fContainer = container;
0f7276b6
GB
93
94 switch (attribute.getAttribute(TmfXmlStrings.TYPE)) {
95 case TmfXmlStrings.TYPE_CONSTANT:
96 fType = StateAttributeType.CONSTANT;
1d7e62f9 97 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
0f7276b6
GB
98 break;
99 case TmfXmlStrings.EVENT_FIELD:
100 fType = StateAttributeType.EVENTFIELD;
1d7e62f9 101 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
0f7276b6
GB
102 break;
103 case TmfXmlStrings.TYPE_LOCATION:
104 fType = StateAttributeType.LOCATION;
1d7e62f9 105 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
0f7276b6
GB
106 break;
107 case TmfXmlStrings.TYPE_QUERY:
4c4e2816 108 List<@Nullable Element> childElements = XmlUtils.getChildElements(attribute);
0f7276b6 109 for (Element subAttributeNode : childElements) {
12685851
GB
110 if (subAttributeNode == null) {
111 continue;
112 }
1d7e62f9 113 ITmfXmlStateAttribute subAttribute = modelFactory.createStateAttribute(subAttributeNode, fContainer);
0f7276b6
GB
114 fQueryList.add(subAttribute);
115 }
116 fType = StateAttributeType.QUERY;
117 fName = null;
118 break;
597168fc
NE
119 case TmfXmlStrings.TYPE_EVENT_NAME:
120 fType = StateAttributeType.EVENTNAME;
121 fName = fContainer.getAttributeValue(attribute.getAttribute(TmfXmlStrings.VALUE));
122 break;
0f7276b6
GB
123 case TmfXmlStrings.NULL:
124 fType = StateAttributeType.NONE;
125 fName = null;
126 break;
1d7e62f9
GB
127 case TmfXmlStrings.TYPE_SELF:
128 fType = StateAttributeType.SELF;
129 fName = null;
130 break;
0f7276b6
GB
131 default:
132 throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$
133 }
134 }
135
136 /**
0b563c20 137 * @since 2.0
1d7e62f9
GB
138 */
139 @Override
0b563c20
JCK
140 public int getAttributeQuark(int startQuark, @Nullable TmfXmlScenarioInfo scenarioInfo) {
141 return getAttributeQuark(null, startQuark, scenarioInfo);
1d7e62f9
GB
142 }
143
144 /**
145 * Basic quark-retrieving method. Pass an attribute in parameter as an array
146 * of strings, the matching quark will be returned. If the attribute does
147 * not exist, it will add the quark to the state system if the context
148 * allows it.
149 *
150 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
151 *
152 * @param path
153 * Full path to the attribute
154 * @return The quark for this attribute
155 * @throws AttributeNotFoundException
156 * The attribute does not exist and cannot be added
157 */
158 protected abstract int getQuarkAbsoluteAndAdd(String... path) throws AttributeNotFoundException;
159
160 /**
161 * Quark-retrieving method, but the attribute is queried starting from the
162 * startNodeQuark. If the attribute does not exist, it will add it to the
163 * state system if the context allows it.
164 *
165 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
166 *
167 * @param startNodeQuark
168 * The quark of the attribute from which 'path' originates.
169 * @param path
170 * Relative path to the attribute
171 * @return The quark for this attribute
172 * @throws AttributeNotFoundException
173 * The attribute does not exist and cannot be added
174 */
175 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark, String... path) throws AttributeNotFoundException;
176
177 /**
178 * Get the state system associated with this attribute's container
179 *
180 * @return The state system associated with this state attribute
0f7276b6 181 */
12685851 182 protected @Nullable ITmfStateSystem getStateSystem() {
1d7e62f9
GB
183 return fContainer.getStateSystem();
184 }
0f7276b6 185
1d7e62f9 186 /**
0b563c20 187 * @since 2.0
1d7e62f9
GB
188 */
189 @Override
0b563c20 190 public int getAttributeQuark(@Nullable ITmfEvent event, int startQuark, @Nullable TmfXmlScenarioInfo scenarioInfo) {
1d7e62f9 191 ITmfStateSystem ss = getStateSystem();
12685851
GB
192 if (ss == null) {
193 throw new IllegalStateException("The state system hasn't been initialized yet"); //$NON-NLS-1$
194 }
0b563c20
JCK
195 String name = nullToEmptyString(fName);
196 if (name.length() > 0 && name.charAt(0) == '#' && scenarioInfo == null) {
197 throw new IllegalStateException("XML Attribute needs " + fName + " but the data is not available."); //$NON-NLS-1$//$NON-NLS-2$
198 }
3a5f73a1
JCK
199 name = name.equals(CURRENT_STATE) ? checkNotNull(scenarioInfo).getActiveState()
200 : fName;
0f7276b6
GB
201
202 try {
203 switch (fType) {
204 case CONSTANT: {
205 int quark;
0b563c20
JCK
206 if (name == null) {
207 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
208 }
3a5f73a1
JCK
209 if (name.equals(CURRENT_SCENARIO)) {
210 return checkNotNull(scenarioInfo).getQuark();
211 }
1d7e62f9 212 if (startQuark == IXmlStateSystemContainer.ROOT_QUARK) {
0b563c20 213 quark = getQuarkAbsoluteAndAdd(name);
0f7276b6 214 } else {
0b563c20 215 quark = getQuarkRelativeAndAdd(startQuark, name);
0f7276b6
GB
216 }
217 return quark;
218 }
219 case EVENTFIELD: {
1d7e62f9
GB
220 int quark = IXmlStateSystemContainer.ERROR_QUARK;
221 if (event == null) {
222 Activator.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
223 return quark;
224 }
12685851 225 if (name == null) {
0b563c20 226 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
12685851
GB
227 }
228 if (name.equals(TmfXmlStrings.CPU)) {
35f39420 229 /* See if the event advertises a CPU aspect */
b3867ecc 230 Integer cpu = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(
b1aad44e 231 event.getTrace(), TmfCpuAspect.class, event);
b3867ecc 232 if (cpu != null) {
b1aad44e 233 quark = getQuarkRelativeAndAdd(startQuark, cpu.toString());
35f39420
AM
234 }
235 } else {
1d7e62f9 236 final ITmfEventField content = event.getContent();
0f7276b6 237 /* stop if the event field doesn't exist */
0b563c20 238 if (content.getField(name) == null) {
1d7e62f9 239 return IXmlStateSystemContainer.ERROR_QUARK;
0f7276b6
GB
240 }
241
0b563c20 242 Object field = content.getField(name).getValue();
0f7276b6
GB
243
244 if (field instanceof String) {
245 String fieldString = (String) field;
1d7e62f9 246 quark = getQuarkRelativeAndAdd(startQuark, fieldString);
0f7276b6
GB
247 } else if (field instanceof Long) {
248 Long fieldLong = (Long) field;
1d7e62f9 249 quark = getQuarkRelativeAndAdd(startQuark, fieldLong.toString());
0f7276b6
GB
250 } else if (field instanceof Integer) {
251 Integer fieldInterger = (Integer) field;
1d7e62f9 252 quark = getQuarkRelativeAndAdd(startQuark, fieldInterger.toString());
0f7276b6 253 }
35f39420 254 }
0f7276b6
GB
255 return quark;
256 }
257 case QUERY: {
258 int quark;
259 ITmfStateValue value = TmfStateValue.nullValue();
1d7e62f9 260 int quarkQuery = IXmlStateSystemContainer.ROOT_QUARK;
0f7276b6 261
1d7e62f9 262 for (ITmfXmlStateAttribute attrib : fQueryList) {
0b563c20 263 quarkQuery = attrib.getAttributeQuark(event, quarkQuery, scenarioInfo);
1d7e62f9 264 if (quarkQuery == IXmlStateSystemContainer.ERROR_QUARK) {
0f7276b6
GB
265 break;
266 }
267 }
268
269 // the query may fail: for example CurrentThread if there
270 // has not been a sched_switch event
1d7e62f9 271 if (quarkQuery != IXmlStateSystemContainer.ERROR_QUARK) {
0f7276b6
GB
272 value = ss.queryOngoingState(quarkQuery);
273 }
274
275 switch (value.getType()) {
276 case INTEGER: {
277 int result = value.unboxInt();
1d7e62f9 278 quark = getQuarkRelativeAndAdd(startQuark, String.valueOf(result));
0f7276b6
GB
279 break;
280 }
281 case LONG: {
282 long result = value.unboxLong();
1d7e62f9 283 quark = getQuarkRelativeAndAdd(startQuark, String.valueOf(result));
0f7276b6
GB
284 break;
285 }
286 case STRING: {
287 String result = value.unboxStr();
1d7e62f9 288 quark = getQuarkRelativeAndAdd(startQuark, result);
0f7276b6
GB
289 break;
290 }
291 case DOUBLE:
292 case NULL:
293 default:
1d7e62f9 294 quark = IXmlStateSystemContainer.ERROR_QUARK; // error
0f7276b6
GB
295 break;
296 }
297 return quark;
298 }
299 case LOCATION: {
300 int quark = startQuark;
0b563c20 301 String idLocation = name;
0f7276b6 302
1d7e62f9
GB
303 /* TODO: Add a fContainer.getLocation(id) method */
304 for (TmfXmlLocation location : fContainer.getLocations()) {
0f7276b6 305 if (location.getId().equals(idLocation)) {
0b563c20 306 quark = location.getLocationQuark(event, quark, scenarioInfo);
1d7e62f9 307 if (quark == IXmlStateSystemContainer.ERROR_QUARK) {
0f7276b6
GB
308 break;
309 }
310 }
311 }
312 return quark;
313 }
597168fc
NE
314 case EVENTNAME: {
315 int quark = IXmlStateSystemContainer.ERROR_QUARK;
316 if (event == null) {
317 Activator.logWarning("XML State attribute: looking for an eventname, but event is null"); //$NON-NLS-1$
318 return quark;
319 }
578716e6 320 quark = getQuarkRelativeAndAdd(startQuark, event.getName());
597168fc
NE
321 return quark;
322 }
1d7e62f9
GB
323 case SELF:
324 return startQuark;
0f7276b6
GB
325 case NONE:
326 default:
327 return startQuark;
328 }
329 } catch (AttributeNotFoundException ae) {
330 /*
331 * This can be happen before the creation of the node for a query in
332 * the state system. Example : current thread before a sched_switch
333 */
1d7e62f9 334 return IXmlStateSystemContainer.ERROR_QUARK;
0f7276b6
GB
335 } catch (StateValueTypeException e) {
336 /*
337 * This would happen if we were trying to push/pop attributes not of
338 * type integer. Which, once again, should never happen.
339 */
340 Activator.logError("StateValueTypeException", e); //$NON-NLS-1$
1d7e62f9 341 return IXmlStateSystemContainer.ERROR_QUARK;
0f7276b6
GB
342 }
343 }
344
446598f9
GB
345 @Override
346 public String toString() {
347 return "TmfXmlStateAttribute " + fType + ": " + fName; //$NON-NLS-1$ //$NON-NLS-2$
348 }
349
52293ccd 350}
This page took 0.090527 seconds and 5 git commands to generate.