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