1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 Ecole Polytechnique de Montreal
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
10 * Florian Wininger - Initial API and implementation
11 ******************************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.model
;
15 import java
.util
.LinkedList
;
16 import java
.util
.List
;
18 import org
.eclipse
.jdt
.annotation
.Nullable
;
19 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.nullToEmptyString
;
20 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
22 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.Activator
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
29 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
30 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.XmlUtils
;
31 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
36 import org
.w3c
.dom
.Element
;
39 * This Class implements a single attribute value in the XML-defined state
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" />
52 * @author Florian Wininger
54 public abstract class TmfXmlStateAttribute
implements ITmfXmlStateAttribute
{
56 private enum StateAttributeType
{
66 private final String SCENARIO_NAME
= "#scenarioName"; //$NON-NLS-1$
68 private final String CURRENT_STATE
= "#currentState"; //$NON-NLS-1$
70 /** Type of attribute */
71 private final StateAttributeType fType
;
73 /** Attribute's name */
74 private final @Nullable String fName
;
76 /** List of attributes for a query */
77 private final List
<ITmfXmlStateAttribute
> fQueryList
= new LinkedList
<>();
79 private final IXmlStateSystemContainer fContainer
;
85 * The factory used to create XML model elements
87 * XML element of the attribute
89 * The state system container this state attribute belongs to
91 protected TmfXmlStateAttribute(ITmfXmlModelFactory modelFactory
, Element attribute
, IXmlStateSystemContainer container
) {
92 fContainer
= container
;
94 switch (attribute
.getAttribute(TmfXmlStrings
.TYPE
)) {
95 case TmfXmlStrings
.TYPE_CONSTANT
:
96 fType
= StateAttributeType
.CONSTANT
;
97 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
99 case TmfXmlStrings
.EVENT_FIELD
:
100 fType
= StateAttributeType
.EVENTFIELD
;
101 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
103 case TmfXmlStrings
.TYPE_LOCATION
:
104 fType
= StateAttributeType
.LOCATION
;
105 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
107 case TmfXmlStrings
.TYPE_QUERY
:
108 List
<@Nullable Element
> childElements
= XmlUtils
.getChildElements(attribute
);
109 for (Element subAttributeNode
: childElements
) {
110 if (subAttributeNode
== null) {
113 ITmfXmlStateAttribute subAttribute
= modelFactory
.createStateAttribute(subAttributeNode
, fContainer
);
114 fQueryList
.add(subAttribute
);
116 fType
= StateAttributeType
.QUERY
;
119 case TmfXmlStrings
.TYPE_EVENT_NAME
:
120 fType
= StateAttributeType
.EVENTNAME
;
121 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
123 case TmfXmlStrings
.NULL
:
124 fType
= StateAttributeType
.NONE
;
127 case TmfXmlStrings
.TYPE_SELF
:
128 fType
= StateAttributeType
.SELF
;
132 throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$
140 public int getAttributeQuark(int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
141 return getAttributeQuark(null, startQuark
, scenarioInfo
);
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
150 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
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
158 protected abstract int getQuarkAbsoluteAndAdd(String
... path
) throws AttributeNotFoundException
;
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.
165 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
167 * @param startNodeQuark
168 * The quark of the attribute from which 'path' originates.
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
175 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark
, String
... path
) throws AttributeNotFoundException
;
178 * Get the state system associated with this attribute's container
180 * @return The state system associated with this state attribute
182 protected @Nullable ITmfStateSystem
getStateSystem() {
183 return fContainer
.getStateSystem();
190 public int getAttributeQuark(@Nullable ITmfEvent event
, int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
191 ITmfStateSystem ss
= getStateSystem();
193 throw new IllegalStateException("The state system hasn't been initialized yet"); //$NON-NLS-1$
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$
199 name
= name
.equals(SCENARIO_NAME
) ?
checkNotNull(scenarioInfo
).getScenarioName() : name
.equals(CURRENT_STATE
) ?
checkNotNull(scenarioInfo
).getActiveState() : fName
;
206 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
208 if (startQuark
== IXmlStateSystemContainer
.ROOT_QUARK
) {
209 quark
= getQuarkAbsoluteAndAdd(name
);
211 quark
= getQuarkRelativeAndAdd(startQuark
, name
);
216 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
218 Activator
.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
222 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
224 if (name
.equals(TmfXmlStrings
.CPU
)) {
225 /* See if the event advertises a CPU aspect */
226 Integer cpu
= TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(
227 event
.getTrace(), TmfCpuAspect
.class, event
);
229 quark
= getQuarkRelativeAndAdd(startQuark
, cpu
.toString());
232 final ITmfEventField content
= event
.getContent();
233 /* stop if the event field doesn't exist */
234 if (content
.getField(name
) == null) {
235 return IXmlStateSystemContainer
.ERROR_QUARK
;
238 Object field
= content
.getField(name
).getValue();
240 if (field
instanceof String
) {
241 String fieldString
= (String
) field
;
242 quark
= getQuarkRelativeAndAdd(startQuark
, fieldString
);
243 } else if (field
instanceof Long
) {
244 Long fieldLong
= (Long
) field
;
245 quark
= getQuarkRelativeAndAdd(startQuark
, fieldLong
.toString());
246 } else if (field
instanceof Integer
) {
247 Integer fieldInterger
= (Integer
) field
;
248 quark
= getQuarkRelativeAndAdd(startQuark
, fieldInterger
.toString());
255 ITmfStateValue value
= TmfStateValue
.nullValue();
256 int quarkQuery
= IXmlStateSystemContainer
.ROOT_QUARK
;
258 for (ITmfXmlStateAttribute attrib
: fQueryList
) {
259 quarkQuery
= attrib
.getAttributeQuark(event
, quarkQuery
, scenarioInfo
);
260 if (quarkQuery
== IXmlStateSystemContainer
.ERROR_QUARK
) {
265 // the query may fail: for example CurrentThread if there
266 // has not been a sched_switch event
267 if (quarkQuery
!= IXmlStateSystemContainer
.ERROR_QUARK
) {
268 value
= ss
.queryOngoingState(quarkQuery
);
271 switch (value
.getType()) {
273 int result
= value
.unboxInt();
274 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
278 long result
= value
.unboxLong();
279 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
283 String result
= value
.unboxStr();
284 quark
= getQuarkRelativeAndAdd(startQuark
, result
);
290 quark
= IXmlStateSystemContainer
.ERROR_QUARK
; // error
296 int quark
= startQuark
;
297 String idLocation
= name
;
299 /* TODO: Add a fContainer.getLocation(id) method */
300 for (TmfXmlLocation location
: fContainer
.getLocations()) {
301 if (location
.getId().equals(idLocation
)) {
302 quark
= location
.getLocationQuark(event
, quark
, scenarioInfo
);
303 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
311 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
313 Activator
.logWarning("XML State attribute: looking for an eventname, but event is null"); //$NON-NLS-1$
316 quark
= getQuarkRelativeAndAdd(startQuark
, event
.getName());
325 } catch (AttributeNotFoundException ae
) {
327 * This can be happen before the creation of the node for a query in
328 * the state system. Example : current thread before a sched_switch
330 return IXmlStateSystemContainer
.ERROR_QUARK
;
331 } catch (StateValueTypeException e
) {
333 * This would happen if we were trying to push/pop attributes not of
334 * type integer. Which, once again, should never happen.
336 Activator
.logError("StateValueTypeException", e
); //$NON-NLS-1$
337 return IXmlStateSystemContainer
.ERROR_QUARK
;
342 public String
toString() {
343 return "TmfXmlStateAttribute " + fType
+ ": " + fName
; //$NON-NLS-1$ //$NON-NLS-2$