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 org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.Activator
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
26 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
27 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.XmlUtils
;
28 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
33 import org
.w3c
.dom
.Element
;
36 * This Class implements a single attribute value in the XML-defined state
41 * <stateAttribute type="constant" value="Threads" />
42 * <stateAttribute type="query" />
43 * <stateAttribute type="constant" value="CPUs" />
44 * <stateAttribute type="eventField" value="cpu" />
45 * <stateAttribute type="constant" value="Current_thread" />
49 * @author Florian Wininger
51 public abstract class TmfXmlStateAttribute
implements ITmfXmlStateAttribute
{
53 private enum StateAttributeType
{
63 /** Type of attribute */
64 private final StateAttributeType fType
;
66 /** Attribute's name */
67 private final @Nullable String fName
;
69 /** List of attributes for a query */
70 private final List
<ITmfXmlStateAttribute
> fQueryList
= new LinkedList
<>();
72 private final IXmlStateSystemContainer fContainer
;
78 * The factory used to create XML model elements
80 * XML element of the attribute
82 * The state system container this state attribute belongs to
84 protected TmfXmlStateAttribute(ITmfXmlModelFactory modelFactory
, Element attribute
, IXmlStateSystemContainer container
) {
85 fContainer
= container
;
87 switch (attribute
.getAttribute(TmfXmlStrings
.TYPE
)) {
88 case TmfXmlStrings
.TYPE_CONSTANT
:
89 fType
= StateAttributeType
.CONSTANT
;
90 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
92 case TmfXmlStrings
.EVENT_FIELD
:
93 fType
= StateAttributeType
.EVENTFIELD
;
94 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
96 case TmfXmlStrings
.TYPE_LOCATION
:
97 fType
= StateAttributeType
.LOCATION
;
98 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
100 case TmfXmlStrings
.TYPE_QUERY
:
101 List
<Element
> childElements
= XmlUtils
.getChildElements(attribute
);
102 for (Element subAttributeNode
: childElements
) {
103 if (subAttributeNode
== null) {
106 ITmfXmlStateAttribute subAttribute
= modelFactory
.createStateAttribute(subAttributeNode
, fContainer
);
107 fQueryList
.add(subAttribute
);
109 fType
= StateAttributeType
.QUERY
;
112 case TmfXmlStrings
.TYPE_EVENT_NAME
:
113 fType
= StateAttributeType
.EVENTNAME
;
114 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
116 case TmfXmlStrings
.NULL
:
117 fType
= StateAttributeType
.NONE
;
120 case TmfXmlStrings
.TYPE_SELF
:
121 fType
= StateAttributeType
.SELF
;
125 throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$
130 * This method gets the quark for this state attribute in the State System.
132 * Unless this attribute is a location, in which case the quark must exist,
133 * the quark will be added to the state system if the state system is in
137 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
138 * search the full attribute tree
139 * @return the quark described by attribute or
140 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
144 public int getAttributeQuark(int startQuark
) {
145 return getAttributeQuark(null, startQuark
);
149 * Basic quark-retrieving method. Pass an attribute in parameter as an array
150 * of strings, the matching quark will be returned. If the attribute does
151 * not exist, it will add the quark to the state system if the context
154 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
157 * Full path to the attribute
158 * @return The quark for this attribute
159 * @throws AttributeNotFoundException
160 * The attribute does not exist and cannot be added
162 protected abstract int getQuarkAbsoluteAndAdd(String
... path
) throws AttributeNotFoundException
;
165 * Quark-retrieving method, but the attribute is queried starting from the
166 * startNodeQuark. If the attribute does not exist, it will add it to the
167 * state system if the context allows it.
169 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
171 * @param startNodeQuark
172 * The quark of the attribute from which 'path' originates.
174 * Relative path to the attribute
175 * @return The quark for this attribute
176 * @throws AttributeNotFoundException
177 * The attribute does not exist and cannot be added
179 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark
, String
... path
) throws AttributeNotFoundException
;
182 * Get the state system associated with this attribute's container
184 * @return The state system associated with this state attribute
186 protected @Nullable ITmfStateSystem
getStateSystem() {
187 return fContainer
.getStateSystem();
191 * This method gets the quark for this state attribute in the State System.
193 * Unless this attribute is a location, in which case the quark must exist,
194 * the quark will be added to the state system if the state system is in
198 * The current event being handled, or <code>null</code> if no
199 * event available in the context
201 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
202 * search the full attribute tree
203 * @return the quark described by attribute or
204 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
208 public int getAttributeQuark(@Nullable ITmfEvent event
, int startQuark
) {
209 ITmfStateSystem ss
= getStateSystem();
211 throw new IllegalStateException("The state system hasn't been initialized yet"); //$NON-NLS-1$
218 if (startQuark
== IXmlStateSystemContainer
.ROOT_QUARK
) {
219 quark
= getQuarkAbsoluteAndAdd(fName
);
221 quark
= getQuarkRelativeAndAdd(startQuark
, fName
);
226 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
228 Activator
.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
231 /* special case if field is CPU which is not in the field */
234 throw new IllegalStateException();
236 if (name
.equals(TmfXmlStrings
.CPU
)) {
237 /* See if the event advertises a CPU aspect */
238 Object cpuObj
= TmfTraceUtils
.resolveEventAspectOfClassForEvent(
239 event
.getTrace(), TmfCpuAspect
.class, event
);
240 if (cpuObj
!= null) {
241 Integer cpu
= (Integer
) cpuObj
;
242 quark
= getQuarkRelativeAndAdd(startQuark
, cpu
.toString());
245 final ITmfEventField content
= event
.getContent();
246 /* stop if the event field doesn't exist */
247 if (content
.getField(fName
) == null) {
248 return IXmlStateSystemContainer
.ERROR_QUARK
;
251 Object field
= content
.getField(fName
).getValue();
253 if (field
instanceof String
) {
254 String fieldString
= (String
) field
;
255 quark
= getQuarkRelativeAndAdd(startQuark
, fieldString
);
256 } else if (field
instanceof Long
) {
257 Long fieldLong
= (Long
) field
;
258 quark
= getQuarkRelativeAndAdd(startQuark
, fieldLong
.toString());
259 } else if (field
instanceof Integer
) {
260 Integer fieldInterger
= (Integer
) field
;
261 quark
= getQuarkRelativeAndAdd(startQuark
, fieldInterger
.toString());
268 ITmfStateValue value
= TmfStateValue
.nullValue();
269 int quarkQuery
= IXmlStateSystemContainer
.ROOT_QUARK
;
271 for (ITmfXmlStateAttribute attrib
: fQueryList
) {
272 quarkQuery
= attrib
.getAttributeQuark(event
, quarkQuery
);
273 if (quarkQuery
== IXmlStateSystemContainer
.ERROR_QUARK
) {
278 // the query may fail: for example CurrentThread if there
279 // has not been a sched_switch event
280 if (quarkQuery
!= IXmlStateSystemContainer
.ERROR_QUARK
) {
281 value
= ss
.queryOngoingState(quarkQuery
);
284 switch (value
.getType()) {
286 int result
= value
.unboxInt();
287 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
291 long result
= value
.unboxLong();
292 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
296 String result
= value
.unboxStr();
297 quark
= getQuarkRelativeAndAdd(startQuark
, result
);
303 quark
= IXmlStateSystemContainer
.ERROR_QUARK
; // error
309 int quark
= startQuark
;
310 String idLocation
= fName
;
312 /* TODO: Add a fContainer.getLocation(id) method */
313 for (TmfXmlLocation location
: fContainer
.getLocations()) {
314 if (location
.getId().equals(idLocation
)) {
315 quark
= location
.getLocationQuark(event
, quark
);
316 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
324 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
326 Activator
.logWarning("XML State attribute: looking for an eventname, but event is null"); //$NON-NLS-1$
329 quark
= getQuarkRelativeAndAdd(startQuark
, event
.getName());
338 } catch (AttributeNotFoundException ae
) {
340 * This can be happen before the creation of the node for a query in
341 * the state system. Example : current thread before a sched_switch
343 return IXmlStateSystemContainer
.ERROR_QUARK
;
344 } catch (StateValueTypeException e
) {
346 * This would happen if we were trying to push/pop attributes not of
347 * type integer. Which, once again, should never happen.
349 Activator
.logError("StateValueTypeException", e
); //$NON-NLS-1$
350 return IXmlStateSystemContainer
.ERROR_QUARK
;
355 public String
toString() {
356 return "TmfXmlStateAttribute " + fType
+ ": " + fName
; //$NON-NLS-1$ //$NON-NLS-2$