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 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();
144 public int getAttributeQuark(int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
145 return getAttributeQuark(null, startQuark
, scenarioInfo
);
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();
194 public int getAttributeQuark(@Nullable ITmfEvent event
, int startQuark
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
195 ITmfStateSystem ss
= getStateSystem();
197 throw new IllegalStateException("The state system hasn't been initialized yet"); //$NON-NLS-1$
199 String name
= nullToEmptyString(fName
);
200 if (name
.length() > 0 && name
.charAt(0) == '#' && scenarioInfo
== null) {
201 throw new IllegalStateException("XML Attribute needs " + fName
+ " but the data is not available."); //$NON-NLS-1$//$NON-NLS-2$
203 name
= name
.equals(CURRENT_STATE
) ?
checkNotNull(scenarioInfo
).getActiveState()
211 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
213 if (name
.equals(CURRENT_SCENARIO
)) {
214 return checkNotNull(scenarioInfo
).getQuark();
216 if (startQuark
== IXmlStateSystemContainer
.ROOT_QUARK
) {
217 quark
= getQuarkAbsoluteAndAdd(name
);
219 quark
= getQuarkRelativeAndAdd(startQuark
, name
);
224 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
226 Activator
.logWarning("XML State attribute: looking for an event field, but event is null"); //$NON-NLS-1$
230 throw new IllegalStateException("Invalid attribute name"); //$NON-NLS-1$
232 if (name
.equals(TmfXmlStrings
.CPU
)) {
233 /* See if the event advertises a CPU aspect */
234 Integer cpu
= TmfTraceUtils
.resolveIntEventAspectOfClassForEvent(
235 event
.getTrace(), TmfCpuAspect
.class, event
);
237 quark
= getQuarkRelativeAndAdd(startQuark
, cpu
.toString());
240 final ITmfEventField content
= event
.getContent();
241 /* stop if the event field doesn't exist */
242 if (content
.getField(name
) == null) {
243 return IXmlStateSystemContainer
.ERROR_QUARK
;
246 Object field
= content
.getField(name
).getValue();
248 if (field
instanceof String
) {
249 String fieldString
= (String
) field
;
250 quark
= getQuarkRelativeAndAdd(startQuark
, fieldString
);
251 } else if (field
instanceof Long
) {
252 Long fieldLong
= (Long
) field
;
253 quark
= getQuarkRelativeAndAdd(startQuark
, fieldLong
.toString());
254 } else if (field
instanceof Integer
) {
255 Integer fieldInterger
= (Integer
) field
;
256 quark
= getQuarkRelativeAndAdd(startQuark
, fieldInterger
.toString());
263 ITmfStateValue value
= TmfStateValue
.nullValue();
264 int quarkQuery
= IXmlStateSystemContainer
.ROOT_QUARK
;
266 for (ITmfXmlStateAttribute attrib
: fQueryList
) {
267 quarkQuery
= attrib
.getAttributeQuark(event
, quarkQuery
, scenarioInfo
);
268 if (quarkQuery
== IXmlStateSystemContainer
.ERROR_QUARK
) {
273 // the query may fail: for example CurrentThread if there
274 // has not been a sched_switch event
275 if (quarkQuery
!= IXmlStateSystemContainer
.ERROR_QUARK
) {
276 value
= ss
.queryOngoingState(quarkQuery
);
279 switch (value
.getType()) {
281 int result
= value
.unboxInt();
282 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
286 long result
= value
.unboxLong();
287 quark
= getQuarkRelativeAndAdd(startQuark
, String
.valueOf(result
));
291 String result
= value
.unboxStr();
292 quark
= getQuarkRelativeAndAdd(startQuark
, result
);
298 quark
= IXmlStateSystemContainer
.ERROR_QUARK
; // error
304 int quark
= startQuark
;
305 String idLocation
= name
;
307 /* TODO: Add a fContainer.getLocation(id) method */
308 for (TmfXmlLocation location
: fContainer
.getLocations()) {
309 if (location
.getId().equals(idLocation
)) {
310 quark
= location
.getLocationQuark(event
, quark
, scenarioInfo
);
311 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
319 int quark
= IXmlStateSystemContainer
.ERROR_QUARK
;
321 Activator
.logWarning("XML State attribute: looking for an eventname, but event is null"); //$NON-NLS-1$
324 quark
= getQuarkRelativeAndAdd(startQuark
, event
.getName());
333 } catch (AttributeNotFoundException ae
) {
335 * This can be happen before the creation of the node for a query in
336 * the state system. Example : current thread before a sched_switch
338 return IXmlStateSystemContainer
.ERROR_QUARK
;
339 } catch (StateValueTypeException e
) {
341 * This would happen if we were trying to push/pop attributes not of
342 * type integer. Which, once again, should never happen.
344 Activator
.logError("StateValueTypeException", e
); //$NON-NLS-1$
345 return IXmlStateSystemContainer
.ERROR_QUARK
;
350 public String
toString() {
351 return "TmfXmlStateAttribute " + fType
+ ": " + fName
; //$NON-NLS-1$ //$NON-NLS-2$