1 /*******************************************************************************
2 * Copyright (c) 2014 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
.w3c
.dom
.Element
;
34 * This Class implements a single attribute value in the XML-defined state
39 * <stateAttribute type="constant" value="Threads" />
40 * <stateAttribute type="query" />
41 * <stateAttribute type="constant" value="CPUs" />
42 * <stateAttribute type="eventField" value="cpu" />
43 * <stateAttribute type="constant" value="Current_thread" />
47 * @author Florian Wininger
49 public abstract class TmfXmlStateAttribute
implements ITmfXmlStateAttribute
{
51 private enum StateAttributeType
{
60 /** Type of attribute */
61 private final StateAttributeType fType
;
63 /** Attribute's name */
64 private final String fName
;
66 /** List of attributes for a query */
67 private final List
<ITmfXmlStateAttribute
> fQueryList
= new LinkedList
<>();
69 private final IXmlStateSystemContainer fContainer
;
75 * The factory used to create XML model elements
77 * XML element of the attribute
79 * The state system container this state attribute belongs to
81 protected TmfXmlStateAttribute(ITmfXmlModelFactory modelFactory
, Element attribute
, IXmlStateSystemContainer container
) {
82 fContainer
= container
;
84 switch (attribute
.getAttribute(TmfXmlStrings
.TYPE
)) {
85 case TmfXmlStrings
.TYPE_CONSTANT
:
86 fType
= StateAttributeType
.CONSTANT
;
87 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
89 case TmfXmlStrings
.EVENT_FIELD
:
90 fType
= StateAttributeType
.EVENTFIELD
;
91 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
93 case TmfXmlStrings
.TYPE_LOCATION
:
94 fType
= StateAttributeType
.LOCATION
;
95 fName
= fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
));
97 case TmfXmlStrings
.TYPE_QUERY
:
98 List
<Element
> childElements
= XmlUtils
.getChildElements(attribute
);
99 for (Element subAttributeNode
: childElements
) {
100 ITmfXmlStateAttribute subAttribute
= modelFactory
.createStateAttribute(subAttributeNode
, fContainer
);
101 fQueryList
.add(subAttribute
);
103 fType
= StateAttributeType
.QUERY
;
106 case TmfXmlStrings
.NULL
:
107 fType
= StateAttributeType
.NONE
;
110 case TmfXmlStrings
.TYPE_SELF
:
111 fType
= StateAttributeType
.SELF
;
115 throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$
120 * This method gets the quark for this state attribute in the State System.
122 * Unless this attribute is a location, in which case the quark must exist,
123 * the quark will be added to the state system if the state system is in
127 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
128 * search the full attribute tree
129 * @return the quark described by attribute or
130 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
134 public int getAttributeQuark(int startQuark
) {
135 return getAttributeQuark(null, startQuark
);
139 * Basic quark-retrieving method. Pass an attribute in parameter as an array
140 * of strings, the matching quark will be returned. If the attribute does
141 * not exist, it will add the quark to the state system if the context
144 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
147 * Full path to the attribute
148 * @return The quark for this attribute
149 * @throws AttributeNotFoundException
150 * The attribute does not exist and cannot be added
152 protected abstract int getQuarkAbsoluteAndAdd(String
... path
) throws AttributeNotFoundException
;
155 * Quark-retrieving method, but the attribute is queried starting from the
156 * startNodeQuark. If the attribute does not exist, it will add it to the
157 * state system if the context allows it.
159 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
161 * @param startNodeQuark
162 * The quark of the attribute from which 'path' originates.
164 * Relative path to the attribute
165 * @return The quark for this attribute
166 * @throws AttributeNotFoundException
167 * The attribute does not exist and cannot be added
169 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark
, String
... path
) throws AttributeNotFoundException
;
172 * Get the state system associated with this attribute's container
174 * @return The state system associated with this state attribute
176 protected ITmfStateSystem
getStateSystem() {
177 return fContainer
.getStateSystem();
181 * This method gets the quark for this state attribute in the State System.
183 * Unless this attribute is a location, in which case the quark must exist,
184 * the quark will be added to the state system if the state system is in
188 * The current event being handled, or <code>null</code> if no
189 * event available in the context
191 * root quark, use {@link IXmlStateSystemContainer#ROOT_QUARK} to
192 * search the full attribute tree
193 * @return the quark described by attribute or
194 * {@link IXmlStateSystemContainer#ERROR_QUARK} if quark cannot be
198 public int getAttributeQuark(@Nullable ITmfEvent event
, int startQuark
) {
199 ITmfStateSystem ss
= getStateSystem();
205 if (startQuark
== IXmlStateSystemContainer
.ROOT_QUARK
) {
206 quark
= getQuarkAbsoluteAndAdd(fName
);
208 quark
= getQuarkRelativeAndAdd(startQuark
, fName
);
213 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
215 Activator
.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
218 /* special case if field is CPU which is not in the field */
219 if (fName
.equals(TmfXmlStrings
.CPU
)) {
220 quark
= getQuarkRelativeAndAdd(startQuark
, event
.getSource());
222 final ITmfEventField content
= event
.getContent();
223 /* stop if the event field doesn't exist */
224 if (content
.getField(fName
) == null) {
225 return IXmlStateSystemContainer
.ERROR_QUARK
;
228 Object field
= content
.getField(fName
).getValue();
230 if (field
instanceof String
) {
231 String fieldString
= (String
) field
;
232 quark
= getQuarkRelativeAndAdd(startQuark
, fieldString
);
233 } else if (field
instanceof Long
) {
234 Long fieldLong
= (Long
) field
;
235 quark
= getQuarkRelativeAndAdd(startQuark
, fieldLong
.toString());
236 } else if (field
instanceof Integer
) {
237 Integer fieldInterger
= (Integer
) field
;
238 quark
= getQuarkRelativeAndAdd(startQuark
, fieldInterger
.toString());
245 ITmfStateValue value
= TmfStateValue
.nullValue();
246 int quarkQuery
= IXmlStateSystemContainer
.ROOT_QUARK
;
248 for (ITmfXmlStateAttribute attrib
: fQueryList
) {
249 quarkQuery
= attrib
.getAttributeQuark(event
, quarkQuery
);
250 if (quarkQuery
== IXmlStateSystemContainer
.ERROR_QUARK
) {
255 // the query may fail: for example CurrentThread if there
256 // has not been a sched_switch event
257 if (quarkQuery
!= IXmlStateSystemContainer
.ERROR_QUARK
) {
258 value
= ss
.queryOngoingState(quarkQuery
);
261 switch (value
.getType()) {
263 int result
= value
.unboxInt();
264 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
268 long result
= value
.unboxLong();
269 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
273 String result
= value
.unboxStr();
274 quark
= getQuarkRelativeAndAdd(startQuark
, result
);
280 quark
= IXmlStateSystemContainer
.ERROR_QUARK
; // error
286 int quark
= startQuark
;
287 String idLocation
= fName
;
289 /* TODO: Add a fContainer.getLocation(id) method */
290 for (TmfXmlLocation location
: fContainer
.getLocations()) {
291 if (location
.getId().equals(idLocation
)) {
292 quark
= location
.getLocationQuark(event
, quark
);
293 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
306 } catch (AttributeNotFoundException ae
) {
308 * This can be happen before the creation of the node for a query in
309 * the state system. Example : current thread before a sched_switch
311 return IXmlStateSystemContainer
.ERROR_QUARK
;
312 } catch (StateValueTypeException e
) {
314 * This would happen if we were trying to push/pop attributes not of
315 * type integer. Which, once again, should never happen.
317 Activator
.logError("StateValueTypeException", e
); //$NON-NLS-1$
318 return IXmlStateSystemContainer
.ERROR_QUARK
;
323 public String
toString() {
324 return "TmfXmlStateAttribute " + fType
+ ": " + fName
; //$NON-NLS-1$ //$NON-NLS-2$