d55dc0307b343171e8402bc78cedabd73716d34f
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / tmf / analysis / xml / core / model / TmfXmlStateValue.java
1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 Ecole Polytechnique de Montreal
3 *
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
8 *
9 * Contributors:
10 * Florian Wininger - Initial API and implementation
11 ******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.analysis.xml.core.model;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import java.util.List;
18
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
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.exceptions.TimeRangeException;
25 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
26 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
27 import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
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.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
32 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
33 import org.w3c.dom.Element;
34
35 /**
36 * This Class implements a State Value in the XML-defined state system, along
37 * with the path to get to the value (either a list of state attributes or an
38 * event field)
39 *
40 * <pre>
41 * Example:
42 * <stateAttribute type="location" value="CurrentThread" />
43 * <stateAttribute type="constant" value="System_call" />
44 * <stateValue type="null" />
45 * </pre>
46 *
47 * @author Florian Wininger
48 */
49 public abstract class TmfXmlStateValue implements ITmfXmlStateValue {
50
51 private final TmfXmlStateValueBase fStateValue;
52
53 /* Path in the State System */
54 private final List<ITmfXmlStateAttribute> fPath;
55 /* Event field to match with this state value */
56 private final @Nullable String fEventField;
57
58 /* Whether this state value is an increment of the previous value */
59 private final boolean fIncrement;
60 /* Stack value */
61 private final ValueTypeStack fStackType;
62 /* Forced value type */
63 private final ITmfStateValue.Type fForcedType;
64
65 private final IXmlStateSystemContainer fContainer;
66
67 /**
68 * Different behaviors of an attribute that is to be stacked
69 */
70 protected enum ValueTypeStack {
71 /** Not stacked */
72 NULL,
73 /** Peek at the value at the top of the stack */
74 PEEK,
75 /** Take the value at the top of the stack */
76 POP,
77 /** Push the value on the stack */
78 PUSH;
79
80 /**
81 * Get the type stack value corresponding to a string
82 *
83 * @param input
84 * The string to match to a value
85 * @return The ValueTypeStack value
86 */
87 public static ValueTypeStack getTypeFromString(String input) {
88 switch (input) {
89 case TmfXmlStrings.STACK_PUSH:
90 return PUSH;
91 case TmfXmlStrings.STACK_POP:
92 return POP;
93 case TmfXmlStrings.STACK_PEEK:
94 return PEEK;
95 default:
96 return NULL;
97 }
98 }
99 }
100
101 /**
102 * Constructor
103 *
104 * @param modelFactory
105 * The factory used to create XML model elements
106 * @param node
107 * The state value XML element
108 * @param container
109 * The state system container this state value belongs to
110 * @param eventField
111 * The event field where to get the value
112 * @param attributes
113 * The attributes representing the path to this value
114 */
115 protected TmfXmlStateValue(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container, List<ITmfXmlStateAttribute> attributes, @Nullable String eventField) {
116 fPath = attributes;
117 fContainer = container;
118 fEventField = eventField;
119 if (!node.getNodeName().equals(TmfXmlStrings.STATE_VALUE)) {
120 throw new IllegalArgumentException("TmfXmlStateValue constructor: Element is not a stateValue"); //$NON-NLS-1$
121 }
122
123 /* Check if there is an increment for the value */
124 fIncrement = Boolean.parseBoolean(node.getAttribute(TmfXmlStrings.INCREMENT));
125
126 /* Process the XML Element state value */
127 fStateValue = initializeStateValue(modelFactory, node);
128
129 /*
130 * Forced type allows to convert the value to a certain type : For
131 * example, a process's TID in an event field may arrive with a LONG
132 * format but we want to store the data in an INT
133 */
134 switch (node.getAttribute(TmfXmlStrings.FORCED_TYPE)) {
135 case TmfXmlStrings.TYPE_STRING:
136 fForcedType = ITmfStateValue.Type.STRING;
137 break;
138 case TmfXmlStrings.TYPE_INT:
139 fForcedType = ITmfStateValue.Type.INTEGER;
140 break;
141 case TmfXmlStrings.TYPE_LONG:
142 fForcedType = ITmfStateValue.Type.LONG;
143 break;
144 default:
145 fForcedType = ITmfStateValue.Type.NULL;
146 }
147
148 /*
149 * Stack Actions : allow to define a stack with PUSH/POP/PEEK methods
150 */
151 String stack = checkNotNull(node.getAttribute(TmfXmlStrings.ATTRIBUTE_STACK));
152 fStackType = ValueTypeStack.getTypeFromString(stack);
153 }
154
155 /**
156 * Initialize a {@link TmfXmlStateValueBase} object for the type and value
157 *
158 * @param modelFactory
159 * The factory used to create XML model elements
160 * @param node
161 * The state value XML element
162 * @return The internal state value type corresponding to this state value
163 */
164 protected TmfXmlStateValueBase initializeStateValue(ITmfXmlModelFactory modelFactory, Element node) {
165 return new TmfXmlStateValueNull();
166 }
167
168 /**
169 * Return the state system container this class is attached to
170 *
171 * @return The state system container
172 */
173 protected IXmlStateSystemContainer getSsContainer() {
174 return fContainer;
175 }
176
177 /**
178 * Get the state system associated with this value's container
179 *
180 * @return The state system associated with the state system container
181 */
182 protected @Nullable ITmfStateSystem getStateSystem() {
183 return fContainer.getStateSystem();
184 }
185
186 /**
187 * Return whether this value is an increment of the previous value
188 *
189 * @return <code>true</code> if the value is an increment
190 */
191 protected boolean isIncrement() {
192 return fIncrement;
193 }
194
195 /**
196 * Get the stack type of this attribute. If the attribute is to be pushed or
197 * popped to a stack. The behavior of the stack attribute will depend on the
198 * implementation of the model.
199 *
200 * @return The stack type of the attribute
201 */
202 protected ValueTypeStack getStackType() {
203 return fStackType;
204 }
205
206 /**
207 * Get the forced type of the value. For example, if the value obtained from
208 * the attributes is not in this forced type, it will be converted to this.
209 *
210 * @return The desired type of the value
211 */
212 protected ITmfStateValue.Type getForcedType() {
213 return fForcedType;
214 }
215
216 /**
217 * Get the current {@link ITmfStateValue} of this state value for an event.
218 * It does not increment the value and does not any other processing of the
219 * value.
220 *
221 * @param event
222 * The current event, or <code>null</code> if no event available.
223 * @return the {@link ITmfStateValue}
224 * @throws AttributeNotFoundException
225 * May be thrown by the state system during the query
226 */
227 @Override
228 public ITmfStateValue getValue(@Nullable ITmfEvent event) throws AttributeNotFoundException {
229 return fStateValue.getValue(event);
230 }
231
232 /**
233 * Get the value of the event field that is the path of this state value
234 *
235 * @param event
236 * The current event
237 * @return the value of the event field
238 */
239 @Override
240 public ITmfStateValue getEventFieldValue(@NonNull ITmfEvent event) {
241 String eventField = fEventField;
242 if (eventField == null) {
243 throw new IllegalStateException();
244 }
245 return getEventFieldValue(event, eventField);
246 }
247
248 /**
249 * Get the value of an event field
250 *
251 * @param event
252 * The current event
253 * @param fieldName
254 * The name of the field of which to get the value
255 * @return The value of the event field
256 */
257 protected ITmfStateValue getEventFieldValue(ITmfEvent event, String fieldName) {
258
259 ITmfStateValue value = TmfStateValue.nullValue();
260
261 final ITmfEventField content = event.getContent();
262
263 /* Exception for "CPU", returns the source of this event */
264 /* FIXME : Nameclash if a eventfield have "cpu" for name. */
265 if (fieldName.equals(TmfXmlStrings.CPU)) {
266 Integer cpu = TmfTraceUtils.resolveIntEventAspectOfClassForEvent(event.getTrace(), TmfCpuAspect.class, event);
267 if (cpu != null) {
268 return TmfStateValue.newValueInt(cpu.intValue());
269 }
270 }
271 /* Exception also for "TIMESTAMP", returns the timestamp of this event */
272 if (fieldName.equals(TmfXmlStrings.TIMESTAMP)) {
273 return TmfStateValue.newValueLong(event.getTimestamp().getValue());
274 }
275 if (content.getField(fieldName) == null) {
276 return value;
277 }
278
279 Object field = content.getField(fieldName).getValue();
280
281 /*
282 * Try to find the right type. The type can be forced by
283 * "forcedType" argument.
284 */
285
286 if (field instanceof String) {
287 String fieldString = (String) field;
288
289 switch (fForcedType) {
290 case INTEGER:
291 value = TmfStateValue.newValueInt(Integer.parseInt(fieldString));
292 break;
293 case LONG:
294 value = TmfStateValue.newValueLong(Long.parseLong(fieldString));
295 break;
296 case DOUBLE:
297 value = TmfStateValue.newValueDouble(Double.parseDouble(fieldString));
298 break;
299 case NULL:
300 case STRING:
301 default:
302 value = TmfStateValue.newValueString(fieldString);
303 break;
304 }
305 } else if (field instanceof Long) {
306 Long fieldLong = (Long) field;
307
308 switch (fForcedType) {
309 case INTEGER:
310 value = TmfStateValue.newValueInt(fieldLong.intValue());
311 break;
312 case STRING:
313 value = TmfStateValue.newValueString(fieldLong.toString());
314 break;
315 case DOUBLE:
316 value = TmfStateValue.newValueDouble(fieldLong.doubleValue());
317 break;
318 case LONG:
319 case NULL:
320 default:
321 value = TmfStateValue.newValueLong(fieldLong);
322 break;
323 }
324 } else if (field instanceof Integer) {
325 Integer fieldInteger = (Integer) field;
326
327 switch (fForcedType) {
328 case LONG:
329 value = TmfStateValue.newValueLong(fieldInteger.longValue());
330 break;
331 case STRING:
332 value = TmfStateValue.newValueString(fieldInteger.toString());
333 break;
334 case DOUBLE:
335 value = TmfStateValue.newValueDouble(fieldInteger.doubleValue());
336 break;
337 case INTEGER:
338 case NULL:
339 default:
340 value = TmfStateValue.newValueInt(fieldInteger);
341 break;
342 }
343 } else if (field instanceof Double) {
344 Double fieldDouble = (Double) field;
345
346 switch (fForcedType) {
347 case LONG:
348 value = TmfStateValue.newValueLong(fieldDouble.longValue());
349 break;
350 case STRING:
351 value = TmfStateValue.newValueString(fieldDouble.toString());
352 break;
353 case INTEGER:
354 value = TmfStateValue.newValueInt(fieldDouble.intValue());
355 break;
356 case DOUBLE:
357 case NULL:
358 default:
359 value = TmfStateValue.newValueDouble(fieldDouble);
360 break;
361 }
362 }
363 return value;
364 }
365
366 /**
367 * Get the list of state attributes, the path to the state value
368 *
369 * @return the list of Attribute to have the path in the State System
370 */
371 @Override
372 public List<ITmfXmlStateAttribute> getAttributes() {
373 return fPath;
374 }
375
376 /**
377 * Handles an event, by setting the value of the attribute described by the
378 * state attribute path in the state system.
379 *
380 * @param event
381 * The event to process
382 * @throws AttributeNotFoundException
383 * Pass through the exception it received
384 * @throws TimeRangeException
385 * Pass through the exception it received
386 * @throws StateValueTypeException
387 * Pass through the exception it received
388 */
389 @Override
390 public void handleEvent(@NonNull ITmfEvent event) throws AttributeNotFoundException, StateValueTypeException, TimeRangeException {
391 int quark = IXmlStateSystemContainer.ROOT_QUARK;
392
393 for (ITmfXmlStateAttribute attribute : fPath) {
394 quark = attribute.getAttributeQuark(event, quark);
395 /* the query is not valid, we stop the state change */
396 if (quark == IXmlStateSystemContainer.ERROR_QUARK) {
397 throw new AttributeNotFoundException("Not found XML attribute " + attribute); //$NON-NLS-1$
398 }
399 }
400
401 long ts = event.getTimestamp().getValue();
402 fStateValue.handleEvent(event, quark, ts);
403 }
404
405 @Override
406 public String toString() {
407 return "TmfXmlStateValue: " + fStateValue; //$NON-NLS-1$
408 }
409
410 /**
411 * Base class for all state values. Contain default methods to handle event,
412 * process or increment the value
413 */
414 protected abstract class TmfXmlStateValueBase {
415
416 /**
417 * Get the value associated with this state value.
418 *
419 * @param event
420 * The event which can be used to retrieve the value if
421 * necessary. The event can be <code>null</code> if no event
422 * is required.
423 * @return The state value corresponding to this XML state value
424 * @throws AttributeNotFoundException
425 * Pass through the exception it received
426 */
427 public abstract ITmfStateValue getValue(@Nullable ITmfEvent event) throws AttributeNotFoundException;
428
429 /**
430 * Do something with the state value, possibly using an event
431 *
432 * @param event
433 * The event being handled. If there is no event is
434 * available, use <code>null</code>.
435 * @param quark
436 * The quark for this value
437 * @param timestamp
438 * The timestamp of the event
439 * @throws StateValueTypeException
440 * Pass through the exception it received
441 * @throws TimeRangeException
442 * Pass through the exception it received
443 * @throws AttributeNotFoundException
444 * Pass through the exception it received
445 */
446 public void handleEvent(ITmfEvent event, int quark, long timestamp) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
447 if (fIncrement) {
448 incrementValue(event, quark, timestamp);
449 } else {
450 ITmfStateValue value = getValue(event);
451 processValue(quark, timestamp, value);
452 }
453 }
454
455 /**
456 * Set the value of a quark at a given timestamp.
457 *
458 * @param quark
459 * The quark for this value
460 * @param timestamp
461 * The timestamp
462 * @param value
463 * The value of this state value
464 * @throws TimeRangeException
465 * Pass through the exception it received
466 * @throws StateValueTypeException
467 * Pass through the exception it received
468 * @throws AttributeNotFoundException
469 * Pass through the exception it received
470 */
471 @SuppressWarnings("unused")
472 protected void processValue(int quark, long timestamp, ITmfStateValue value) throws TimeRangeException, StateValueTypeException, AttributeNotFoundException {
473 }
474
475 /**
476 * Increments the value of the parameter
477 *
478 * @param event
479 * The event being handled
480 * @param quark
481 * The quark for this value
482 * @param timestamp
483 * The timestamp of the event
484 * @throws StateValueTypeException
485 * Pass through the exception it received
486 * @throws TimeRangeException
487 * Pass through the exception it received
488 * @throws AttributeNotFoundException
489 * Pass through the exception it received
490 */
491 @SuppressWarnings("unused")
492 protected void incrementValue(ITmfEvent event, int quark, long timestamp) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
493 }
494 }
495
496 /* This state value uses a constant value, defined in the XML */
497 private class TmfXmlStateValueNull extends TmfXmlStateValueBase {
498
499 @Override
500 public ITmfStateValue getValue(@Nullable ITmfEvent event) throws AttributeNotFoundException {
501 return TmfStateValue.nullValue();
502 }
503
504 }
505
506 }
This page took 0.042128 seconds and 4 git commands to generate.