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