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