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