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 static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.nullToEmptyString
;
18 import java
.util
.LinkedList
;
19 import java
.util
.List
;
21 import org
.eclipse
.jdt
.annotation
.Nullable
;
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
.statesystem
.core
.ITmfStateSystem
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
30 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
31 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.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
.ITmfEventAspect
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
37 import org
.w3c
.dom
.Element
;
40 * This Class implements a single attribute value in the XML-defined state
45 * <stateAttribute type="constant" value="Threads" />
46 * <stateAttribute type="query" />
47 * <stateAttribute type="constant" value="CPUs" />
48 * <stateAttribute type="eventField" value="cpu" />
49 * <stateAttribute type="constant" value="Current_thread" />
53 * @author Florian Wininger
55 public abstract class TmfXmlStateAttribute
implements ITmfXmlStateAttribute
{
57 private enum StateAttributeType
{
67 private final String CURRENT_STATE
= "#currentState"; //$NON-NLS-1$
69 private final String CURRENT_SCENARIO
= "#CurrentScenario"; //$NON-NLS-1$
71 /** Type of attribute */
72 private final StateAttributeType fType
;
74 /** Attribute's name */
75 private final @Nullable String fName
;
77 /** List of attributes for a query */
78 private final List
<ITmfXmlStateAttribute
> fQueryList
= new LinkedList
<>();
80 private final IXmlStateSystemContainer fContainer
;
86 * The factory used to create XML model elements
88 * XML element of the attribute
90 * The state system container this state attribute belongs to
92 protected TmfXmlStateAttribute(ITmfXmlModelFactory modelFactory
, Element attribute
, IXmlStateSystemContainer container
) {
93 fContainer
= container
;
95 switch (attribute
.getAttribute(TmfXmlStrings
.TYPE
)) {
96 case TmfXmlStrings
.TYPE_CONSTANT
:
97 fType
= StateAttributeType
.CONSTANT
;
98 fName
= getAttributeName(attribute
);
100 case TmfXmlStrings
.EVENT_FIELD
:
101 fType
= StateAttributeType
.EVENTFIELD
;
102 fName
= getAttributeName(attribute
);
104 case TmfXmlStrings
.TYPE_LOCATION
:
105 fType
= StateAttributeType
.LOCATION
;
106 fName
= getAttributeName(attribute
);
108 case TmfXmlStrings
.TYPE_QUERY
:
109 List
<@Nullable Element
> childElements
= XmlUtils
.getChildElements(attribute
);
110 for (Element subAttributeNode
: childElements
) {
111 if (subAttributeNode
== null) {
114 ITmfXmlStateAttribute subAttribute
= modelFactory
.createStateAttribute(subAttributeNode
, fContainer
);
115 fQueryList
.add(subAttribute
);
117 fType
= StateAttributeType
.QUERY
;
120 case TmfXmlStrings
.TYPE_EVENT_NAME
:
121 fType
= StateAttributeType
.EVENTNAME
;
122 fName
= getAttributeName(attribute
);
124 case TmfXmlStrings
.NULL
:
125 fType
= StateAttributeType
.NONE
;
128 case TmfXmlStrings
.TYPE_SELF
:
129 fType
= StateAttributeType
.SELF
;
133 throw new IllegalArgumentException("TmfXmlStateAttribute constructor: The XML element is not of the right type"); //$NON-NLS-1$
137 private String
getAttributeName(Element attribute
) {
138 return fContainer
.getAttributeValue(attribute
.getAttribute(TmfXmlStrings
.VALUE
)).intern();
142 public int getAttributeQuark(int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
143 return getAttributeQuark(null, startQuark
, scenarioInfo
);
147 * Basic quark-retrieving method. Pass an attribute in parameter as an array
148 * of strings, the matching quark will be returned. If the attribute does
149 * not exist, it will add the quark to the state system if the context
152 * See {@link ITmfStateSystemBuilder#getQuarkAbsoluteAndAdd(String...)}
155 * Full path to the attribute
156 * @return The quark for this attribute
157 * @throws AttributeNotFoundException
158 * The attribute does not exist and cannot be added
160 protected abstract int getQuarkAbsoluteAndAdd(String
... path
) throws AttributeNotFoundException
;
163 * Quark-retrieving method, but the attribute is queried starting from the
164 * startNodeQuark. If the attribute does not exist, it will add it to the
165 * state system if the context allows it.
167 * See {@link ITmfStateSystemBuilder#getQuarkRelativeAndAdd(int, String...)}
169 * @param startNodeQuark
170 * The quark of the attribute from which 'path' originates.
172 * Relative path to the attribute
173 * @return The quark for this attribute
174 * @throws AttributeNotFoundException
175 * The attribute does not exist and cannot be added
177 protected abstract int getQuarkRelativeAndAdd(int startNodeQuark
, String
... path
) throws AttributeNotFoundException
;
180 * Get the state system associated with this attribute's container
182 * @return The state system associated with this state attribute
184 protected @Nullable ITmfStateSystem
getStateSystem() {
185 return fContainer
.getStateSystem();
189 public int getAttributeQuark(@Nullable ITmfEvent event
, int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
190 ITmfStateSystem ss
= getStateSystem();
192 throw new IllegalStateException("The state system hasn't been initialized yet"); //$NON-NLS-1$
194 String name
= nullToEmptyString(fName
);
195 if (name
.length() > 0 && name
.charAt(0) == '#' && scenarioInfo
== null) {
196 throw new IllegalStateException("XML Attribute needs " + fName
+ " but the data is not available."); //$NON-NLS-1$//$NON-NLS-2$
198 name
= name
.equals(CURRENT_STATE
) ?
checkNotNull(scenarioInfo
).getActiveState()
206 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
208 if (name
.equals(CURRENT_SCENARIO
)) {
209 return checkNotNull(scenarioInfo
).getQuark();
211 if (startQuark
== IXmlStateSystemContainer
.ROOT_QUARK
) {
212 quark
= getQuarkAbsoluteAndAdd(name
);
214 quark
= getQuarkRelativeAndAdd(startQuark
, name
);
219 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
221 Activator
.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
225 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
228 Object fieldValue
= null;
229 /* First, look for a field with the given name */
230 ITmfEventField field
= event
.getContent().getField(name
);
231 /* Field not found, see if it is a special case field */
233 if (name
.equalsIgnoreCase(TmfXmlStrings
.CPU
)) {
234 /* See if the event advertises a CPU aspect */
235 Integer cpu
= TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(
236 event
.getTrace(), TmfCpuAspect
.class, event
);
238 return getQuarkRelativeAndAdd(startQuark
, cpu
.toString());
240 return IXmlStateSystemContainer
.ERROR_QUARK
;
242 /* Search between the trace event aspects */
243 for (ITmfEventAspect
<?
> aspect
: event
.getTrace().getEventAspects()) {
244 if (aspect
.getName().equals(fName
)) {
245 fieldValue
= aspect
.resolve(event
);
250 fieldValue
= field
.getValue();
253 if (fieldValue
instanceof String
) {
254 String fieldString
= (String
) fieldValue
;
255 quark
= getQuarkRelativeAndAdd(startQuark
, fieldString
);
256 } else if (fieldValue
instanceof Long
) {
257 Long fieldLong
= (Long
) fieldValue
;
258 quark
= getQuarkRelativeAndAdd(startQuark
, fieldLong
.toString());
259 } else if (fieldValue
instanceof Integer
) {
260 Integer fieldInterger
= (Integer
) fieldValue
;
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
, scenarioInfo
);
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
);
304 quark
= IXmlStateSystemContainer
.ERROR_QUARK
; // error
310 int quark
= startQuark
;
311 String idLocation
= name
;
313 /* TODO: Add a fContainer.getLocation(id) method */
314 for (TmfXmlLocation location
: fContainer
.getLocations()) {
315 if (location
.getId().equals(idLocation
)) {
316 quark
= location
.getLocationQuark(event
, quark
, scenarioInfo
);
317 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
325 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
327 Activator
.logWarning("XML State attribute: looking for an eventname, but event is null"); //$NON-NLS-1$
330 quark
= getQuarkRelativeAndAdd(startQuark
, event
.getName());
339 } catch (AttributeNotFoundException ae
) {
341 * This can be happen before the creation of the node for a query in
342 * the state system. Example : current thread before a sched_switch
344 return IXmlStateSystemContainer
.ERROR_QUARK
;
345 } catch (StateValueTypeException e
) {
347 * This would happen if we were trying to push/pop attributes not of
348 * type integer. Which, once again, should never happen.
350 Activator
.logError("StateValueTypeException", e
); //$NON-NLS-1$
351 return IXmlStateSystemContainer
.ERROR_QUARK
;
356 public String
toString() {
357 return "TmfXmlStateAttribute " + fType
+ ": " + fName
; //$NON-NLS-1$ //$NON-NLS-2$