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
.internal
.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
.internal
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
24 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.module
.XmlUtils
;
25 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
30 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
31 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
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 CURRENT_STATE
= "#currentState"; //$NON-NLS-1$
68 private final String CURRENT_SCENARIO
= "#CurrentScenario"; //$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
= getAttributeName(attribute
);
99 case TmfXmlStrings
.EVENT_FIELD
:
100 fType
= StateAttributeType
.EVENTFIELD
;
101 fName
= getAttributeName(attribute
);
103 case TmfXmlStrings
.TYPE_LOCATION
:
104 fType
= StateAttributeType
.LOCATION
;
105 fName
= getAttributeName(attribute
);
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
= getAttributeName(attribute
);
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$
136 private String
getAttributeName(Element attribute
) {
137 return fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
)).intern();
141 public int getAttributeQuark(int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
142 return getAttributeQuark(null, startQuark
, scenarioInfo
);
146 * Basic quark-retrieving method. Pass an attribute in parameter as an array
147 * of strings, the matching quark will be returned. If the attribute does
148 * not exist, it will add the quark to the state system if the context
151 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
154 * Full path to the attribute
155 * @return The quark for this attribute
156 * @throws AttributeNotFoundException
157 * The attribute does not exist and cannot be added
159 protected abstract int getQuarkAbsoluteAndAdd(String
... path
) throws AttributeNotFoundException
;
162 * Quark-retrieving method, but the attribute is queried starting from the
163 * startNodeQuark. If the attribute does not exist, it will add it to the
164 * state system if the context allows it.
166 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
168 * @param startNodeQuark
169 * The quark of the attribute from which 'path' originates.
171 * Relative path to the attribute
172 * @return The quark for this attribute
173 * @throws AttributeNotFoundException
174 * The attribute does not exist and cannot be added
176 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark
, String
... path
) throws AttributeNotFoundException
;
179 * Get the state system associated with this attribute's container
181 * @return The state system associated with this state attribute
183 protected @Nullable ITmfStateSystem
getStateSystem() {
184 return fContainer
.getStateSystem();
188 public int getAttributeQuark(@Nullable ITmfEvent event
, int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
189 ITmfStateSystem ss
= getStateSystem();
191 throw new IllegalStateException("The state system hasn't been initialized yet"); //$NON-NLS-1$
193 String name
= nullToEmptyString(fName
);
194 if (name
.length() > 0 && name
.charAt(0) == '#' && scenarioInfo
== null) {
195 throw new IllegalStateException("XML Attribute needs " + fName
+ " but the data is not available."); //$NON-NLS-1$//$NON-NLS-2$
197 name
= name
.equals(CURRENT_STATE
) ?
checkNotNull(scenarioInfo
).getActiveState()
205 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
207 if (name
.equals(CURRENT_SCENARIO
)) {
208 return checkNotNull(scenarioInfo
).getQuark();
210 if (startQuark
== IXmlStateSystemContainer
.ROOT_QUARK
) {
211 quark
= getQuarkAbsoluteAndAdd(name
);
213 quark
= getQuarkRelativeAndAdd(startQuark
, name
);
218 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
220 Activator
.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
224 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
226 /* First, look for a field with the given name */
227 ITmfEventField field
= event
.getContent().getField(name
);
228 /* Field not found, see if it is a special case field */
230 if (name
.equalsIgnoreCase(TmfXmlStrings
.CPU
)) {
231 /* See if the event advertises a CPU aspect */
232 Integer cpu
= TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(
233 event
.getTrace(), TmfCpuAspect
.class, event
);
235 return getQuarkRelativeAndAdd(startQuark
, cpu
.toString());
238 return IXmlStateSystemContainer
.ERROR_QUARK
;
240 Object fieldValue
= field
.getValue();
242 if (fieldValue
instanceof String
) {
243 String fieldString
= (String
) fieldValue
;
244 quark
= getQuarkRelativeAndAdd(startQuark
, fieldString
);
245 } else if (fieldValue
instanceof Long
) {
246 Long fieldLong
= (Long
) fieldValue
;
247 quark
= getQuarkRelativeAndAdd(startQuark
, fieldLong
.toString());
248 } else if (fieldValue
instanceof Integer
) {
249 Integer fieldInterger
= (Integer
) fieldValue
;
250 quark
= getQuarkRelativeAndAdd(startQuark
, fieldInterger
.toString());
256 ITmfStateValue value
= TmfStateValue
.nullValue();
257 int quarkQuery
= IXmlStateSystemContainer
.ROOT_QUARK
;
259 for (ITmfXmlStateAttribute attrib
: fQueryList
) {
260 quarkQuery
= attrib
.getAttributeQuark(event
, quarkQuery
, scenarioInfo
);
261 if (quarkQuery
== IXmlStateSystemContainer
.ERROR_QUARK
) {
266 // the query may fail: for example CurrentThread if there
267 // has not been a sched_switch event
268 if (quarkQuery
!= IXmlStateSystemContainer
.ERROR_QUARK
) {
269 value
= ss
.queryOngoingState(quarkQuery
);
272 switch (value
.getType()) {
274 int result
= value
.unboxInt();
275 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
279 long result
= value
.unboxLong();
280 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
284 String result
= value
.unboxStr();
285 quark
= getQuarkRelativeAndAdd(startQuark
, result
);
292 quark
= IXmlStateSystemContainer
.ERROR_QUARK
; // error
298 int quark
= startQuark
;
299 String idLocation
= name
;
301 /* TODO: Add a fContainer.getLocation(id) method */
302 for (TmfXmlLocation location
: fContainer
.getLocations()) {
303 if (location
.getId().equals(idLocation
)) {
304 quark
= location
.getLocationQuark(event
, quark
, scenarioInfo
);
305 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
313 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
315 Activator
.logWarning("XML State attribute: looking for an eventname, but event is null"); //$NON-NLS-1$
318 quark
= getQuarkRelativeAndAdd(startQuark
, event
.getName());
327 } catch (AttributeNotFoundException ae
) {
329 * This can be happen before the creation of the node for a query in
330 * the state system. Example : current thread before a sched_switch
332 return IXmlStateSystemContainer
.ERROR_QUARK
;
333 } catch (StateValueTypeException e
) {
335 * This would happen if we were trying to push/pop attributes not of
336 * type integer. Which, once again, should never happen.
338 Activator
.logError("StateValueTypeException", e
); //$NON-NLS-1$
339 return IXmlStateSystemContainer
.ERROR_QUARK
;
344 public String
toString() {
345 return "TmfXmlStateAttribute " + fType
+ ": " + fName
; //$NON-NLS-1$ //$NON-NLS-2$