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
.List
;
17 import org
.eclipse
.jdt
.annotation
.NonNull
;
18 import org
.eclipse
.jdt
.annotation
.Nullable
;
19 import org
.eclipse
.linuxtools
.statesystem
.core
.ITmfStateSystem
;
20 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
21 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.StateValueTypeException
;
22 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.TimeRangeException
;
23 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.ITmfStateValue
;
24 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.TmfStateValue
;
25 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
26 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
29 import org
.w3c
.dom
.Element
;
32 * This Class implements a State Value in the XML-defined state system, along
33 * with the path to get to the value (either a list of state attributes or an
38 * <stateAttribute type="location" value="CurrentThread" />
39 * <stateAttribute type="constant" value="System_call" />
40 * <stateValue type="null" />
43 * @author Florian Wininger
45 public abstract class TmfXmlStateValue
implements ITmfXmlStateValue
{
47 private final TmfXmlStateValueBase fStateValue
;
49 /* Path in the State System */
50 private final List
<ITmfXmlStateAttribute
> fPath
;
51 /* Event field to match with this state value */
52 private final String fEventField
;
54 /* Whether this state value is an increment of the previous value */
55 private final boolean fIncrement
;
57 private final ValueTypeStack fStackType
;
58 /* Forced value type */
59 private final ITmfStateValue
.Type fForcedType
;
61 private final IXmlStateSystemContainer fContainer
;
64 * Different behaviors of an attribute that is to be stacked
66 protected enum ValueTypeStack
{
69 /** Peek at the value at the top of the stack */
71 /** Take the value at the top of the stack */
73 /** Push the value on the stack */
77 * Get the type stack value corresponding to a string
80 * The string to match to a value
81 * @return The ValueTypeStack value
83 public static ValueTypeStack
getTypeFromString(String input
) {
85 case TmfXmlStrings
.STACK_PUSH
:
87 case TmfXmlStrings
.STACK_POP
:
89 case TmfXmlStrings
.STACK_PEEK
:
100 * @param modelFactory
101 * The factory used to create XML model elements
103 * The state value XML element
105 * The state system container this state value belongs to
107 * The event field where to get the value
109 * The attributes representing the path to this value
111 protected TmfXmlStateValue(ITmfXmlModelFactory modelFactory
, Element node
, IXmlStateSystemContainer container
, List
<ITmfXmlStateAttribute
> attributes
, String eventField
) {
113 fContainer
= container
;
114 fEventField
= eventField
;
115 if (!node
.getNodeName().equals(TmfXmlStrings
.STATE_VALUE
)) {
116 throw new IllegalArgumentException("TmfXmlStateValue constructor: Element is not a stateValue"); //$NON-NLS-1$
119 /* Check if there is an increment for the value */
120 fIncrement
= Boolean
.parseBoolean(node
.getAttribute(TmfXmlStrings
.INCREMENT
));
122 /* Process the XML Element state value */
123 fStateValue
= initializeStateValue(modelFactory
, node
);
126 * Forced type allows to convert the value to a certain type : For
127 * example, a process's TID in an event field may arrive with a LONG
128 * format but we want to store the data in an INT
130 switch (node
.getAttribute(TmfXmlStrings
.FORCED_TYPE
)) {
131 case TmfXmlStrings
.TYPE_STRING
:
132 fForcedType
= ITmfStateValue
.Type
.STRING
;
134 case TmfXmlStrings
.TYPE_INT
:
135 fForcedType
= ITmfStateValue
.Type
.INTEGER
;
137 case TmfXmlStrings
.TYPE_LONG
:
138 fForcedType
= ITmfStateValue
.Type
.LONG
;
141 fForcedType
= ITmfStateValue
.Type
.NULL
;
145 * Stack Actions : allow to define a stack with PUSH/POP/PEEK methods
147 String stack
= node
.getAttribute(TmfXmlStrings
.ATTRIBUTE_STACK
);
148 fStackType
= ValueTypeStack
.getTypeFromString(stack
);
152 * Initialize a {@link TmfXmlStateValueBase} object for the type and value
154 * @param modelFactory
155 * The factory used to create XML model elements
157 * The state value XML element
158 * @return The internal state value type corresponding to this state value
160 protected TmfXmlStateValueBase
initializeStateValue(ITmfXmlModelFactory modelFactory
, Element node
) {
161 return new TmfXmlStateValueNull();
165 * Return the state system container this class is attached to
167 * @return The state system container
169 protected IXmlStateSystemContainer
getSsContainer() {
174 * Get the state system associated with this value's container
176 * @return The state system associated with the state system container
178 protected ITmfStateSystem
getStateSystem() {
179 return fContainer
.getStateSystem();
183 * Return whether this value is an increment of the previous value
185 * @return <code>true</code> if the value is an increment
187 protected boolean isIncrement() {
192 * Get the stack type of this attribute. If the attribute is to be pushed or
193 * popped to a stack. The behavior of the stack attribute will depend on the
194 * implementation of the model.
196 * @return The stack type of the attribute
198 protected ValueTypeStack
getStackType() {
203 * Get the forced type of the value. For example, if the value obtained from
204 * the attributes is not in this forced type, it will be converted to this.
206 * @return The desired type of the value
208 protected ITmfStateValue
.Type
getForcedType() {
213 * Get the current {@link ITmfStateValue} of this state value for an event.
214 * It does not increment the value and does not any other processing of the
218 * The current event, or <code>null</code> if no event available.
219 * @return the {@link ITmfStateValue}
220 * @throws AttributeNotFoundException
221 * May be thrown by the state system during the query
224 public ITmfStateValue
getValue(@Nullable ITmfEvent event
) throws AttributeNotFoundException
{
225 return fStateValue
.getValue(event
);
229 * Get the value of the event field that is the path of this state value
233 * @return the value of the event field
236 public ITmfStateValue
getEventFieldValue(@NonNull ITmfEvent event
) {
237 return getEventFieldValue(event
, fEventField
);
241 * Get the value of an event field
246 * The name of the field of which to get the value
247 * @return The value of the event field
249 protected ITmfStateValue
getEventFieldValue(@NonNull ITmfEvent event
, String fieldName
) {
251 ITmfStateValue value
= TmfStateValue
.nullValue();
253 final ITmfEventField content
= event
.getContent();
255 /* Exception for "CPU", returns the source of this event */
256 /* FIXME : Nameclash if a eventfield have "cpu" for name. */
257 if (fieldName
.equals(TmfXmlStrings
.CPU
)) {
258 return TmfStateValue
.newValueInt(Integer
.valueOf(event
.getSource()));
260 /* Exception also for "TIMESTAMP", returns the timestamp of this event */
261 if (fieldName
.equals(TmfXmlStrings
.TIMESTAMP
)) {
262 return TmfStateValue
.newValueLong(event
.getTimestamp().getValue());
264 if (content
.getField(fieldName
) == null) {
268 Object field
= content
.getField(fieldName
).getValue();
271 * Try to find the right type. The type can be forced by
272 * "forcedType" argument.
275 if (field
instanceof String
) {
276 String fieldString
= (String
) field
;
278 switch (fForcedType
) {
280 value
= TmfStateValue
.newValueInt(Integer
.parseInt(fieldString
));
283 value
= TmfStateValue
.newValueLong(Long
.parseLong(fieldString
));
286 value
= TmfStateValue
.newValueDouble(Double
.parseDouble(fieldString
));
291 value
= TmfStateValue
.newValueString(fieldString
);
294 } else if (field
instanceof Long
) {
295 Long fieldLong
= (Long
) field
;
297 switch (fForcedType
) {
299 value
= TmfStateValue
.newValueInt(fieldLong
.intValue());
302 value
= TmfStateValue
.newValueString(fieldLong
.toString());
305 value
= TmfStateValue
.newValueDouble(fieldLong
.doubleValue());
310 value
= TmfStateValue
.newValueLong(fieldLong
);
313 } else if (field
instanceof Integer
) {
314 Integer fieldInteger
= (Integer
) field
;
316 switch (fForcedType
) {
318 value
= TmfStateValue
.newValueLong(fieldInteger
.longValue());
321 value
= TmfStateValue
.newValueString(fieldInteger
.toString());
324 value
= TmfStateValue
.newValueDouble(fieldInteger
.doubleValue());
329 value
= TmfStateValue
.newValueInt(fieldInteger
);
332 } else if (field
instanceof Double
) {
333 Double fieldDouble
= (Double
) field
;
335 switch (fForcedType
) {
337 value
= TmfStateValue
.newValueLong(fieldDouble
.longValue());
340 value
= TmfStateValue
.newValueString(fieldDouble
.toString());
343 value
= TmfStateValue
.newValueInt(fieldDouble
.intValue());
348 value
= TmfStateValue
.newValueDouble(fieldDouble
);
356 * Get the list of state attributes, the path to the state value
358 * @return the list of Attribute to have the path in the State System
361 public List
<ITmfXmlStateAttribute
> getAttributes() {
366 * Handles an event, by setting the value of the attribute described by the
367 * state attribute path in the state system.
370 * The event to process
371 * @throws AttributeNotFoundException
372 * Pass through the exception it received
373 * @throws TimeRangeException
374 * Pass through the exception it received
375 * @throws StateValueTypeException
376 * Pass through the exception it received
379 public void handleEvent(@NonNull ITmfEvent event
) throws AttributeNotFoundException
, StateValueTypeException
, TimeRangeException
{
380 int quark
= IXmlStateSystemContainer
.ROOT_QUARK
;
382 for (ITmfXmlStateAttribute attribute
: fPath
) {
383 quark
= attribute
.getAttributeQuark(event
, quark
);
384 /* the query is not valid, we stop the state change */
385 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
386 throw new AttributeNotFoundException("Not found XML attribute " + attribute
); //$NON-NLS-1$
390 long ts
= event
.getTimestamp().getValue();
391 fStateValue
.handleEvent(event
, quark
, ts
);
395 public String
toString() {
396 return "TmfXmlStateValue: " + fStateValue
; //$NON-NLS-1$
400 * Base class for all state values. Contain default methods to handle event,
401 * process or increment the value
403 protected abstract class TmfXmlStateValueBase
{
406 * Get the value associated with this state value.
409 * The event which can be used to retrieve the value if
410 * necessary. The event can be <code>null</code> if no event
412 * @return The state value corresponding to this XML state value
413 * @throws AttributeNotFoundException
414 * Pass through the exception it received
416 public abstract ITmfStateValue
getValue(@Nullable ITmfEvent event
) throws AttributeNotFoundException
;
419 * Do something with the state value, possibly using an event
422 * The event being handled. If there is no event is
423 * available, use <code>null</code>.
425 * The quark for this value
427 * The timestamp of the event
428 * @throws StateValueTypeException
429 * Pass through the exception it received
430 * @throws TimeRangeException
431 * Pass through the exception it received
432 * @throws AttributeNotFoundException
433 * Pass through the exception it received
435 public void handleEvent(@NonNull ITmfEvent event
, int quark
, long timestamp
) throws StateValueTypeException
, TimeRangeException
, AttributeNotFoundException
{
437 incrementValue(event
, quark
, timestamp
);
439 ITmfStateValue value
= getValue(event
);
440 processValue(quark
, timestamp
, value
);
445 * Set the value of a quark at a given timestamp.
448 * The quark for this value
452 * The value of this state value
453 * @throws TimeRangeException
454 * Pass through the exception it received
455 * @throws StateValueTypeException
456 * Pass through the exception it received
457 * @throws AttributeNotFoundException
458 * Pass through the exception it received
460 @SuppressWarnings("unused")
461 protected void processValue(int quark
, long timestamp
, ITmfStateValue value
) throws TimeRangeException
, StateValueTypeException
, AttributeNotFoundException
{
465 * Increments the value of the parameter
468 * The event being handled
470 * The quark for this value
472 * The timestamp of the event
473 * @throws StateValueTypeException
474 * Pass through the exception it received
475 * @throws TimeRangeException
476 * Pass through the exception it received
477 * @throws AttributeNotFoundException
478 * Pass through the exception it received
480 @SuppressWarnings("unused")
481 protected void incrementValue(ITmfEvent event
, int quark
, long timestamp
) throws StateValueTypeException
, TimeRangeException
, AttributeNotFoundException
{
485 /* This state value uses a constant value, defined in the XML */
486 private class TmfXmlStateValueNull
extends TmfXmlStateValueBase
{
489 public ITmfStateValue
getValue(@Nullable ITmfEvent event
) throws AttributeNotFoundException
{
490 return TmfStateValue
.nullValue();