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