tmf.xml: Add support for peek() stack operation
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / internal / tmf / analysis / xml / core / model / readwrite / TmfXmlReadWriteStateValue.java
1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.readwrite;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
21 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.ITmfXmlModelFactory;
22 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.ITmfXmlStateAttribute;
23 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlScenarioInfo;
24 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlStateValue;
25 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
26 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
27 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
28 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
29 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
30 import org.eclipse.tracecompass.statesystem.core.StateSystemBuilderUtils;
31 import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
32 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
33 import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
34 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
35 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
36 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
37 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
38 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
39 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
40 import org.w3c.dom.Element;
41
42 /**
43 * Implements a state value in a read write mode. See {@link TmfXmlStateValue}
44 * for the syntax of the state value.
45 *
46 * In read/write mode, a state value can be considered as an assignation where
47 * the state value is assigned to the quark represented by the state attributes
48 *
49 * @author Geneviève Bastien
50 */
51 public class TmfXmlReadWriteStateValue extends TmfXmlStateValue {
52
53 private static final String ILLEGAL_STATE_EXCEPTION_MESSAGE = "The state system hasn't been initialized yet"; //$NON-NLS-1$
54
55 /**
56 * Constructor where the path to the value is a list of state attributes
57 *
58 * @param modelFactory
59 * The factory used to create XML model elements
60 * @param node
61 * The state value XML element
62 * @param container
63 * The state system container this state value belongs to
64 * @param attributes
65 * The attributes representing the path to this value
66 */
67 public TmfXmlReadWriteStateValue(TmfXmlReadWriteModelFactory modelFactory, Element node, IXmlStateSystemContainer container, List<ITmfXmlStateAttribute> attributes) {
68 this(modelFactory, node, container, attributes, null);
69 }
70
71 /**
72 * Constructor where the path to the value is an event field
73 *
74 * @param modelFactory
75 * The factory used to create XML model elements
76 * @param node
77 * The state value XML element
78 * @param container
79 * The state system container this state value belongs to
80 * @param eventField
81 * The event field where to get the value
82 */
83 public TmfXmlReadWriteStateValue(TmfXmlReadWriteModelFactory modelFactory, Element node, IXmlStateSystemContainer container, String eventField) {
84 this(modelFactory, node, container, new ArrayList<ITmfXmlStateAttribute>(), eventField);
85 }
86
87 private TmfXmlReadWriteStateValue(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container, List<ITmfXmlStateAttribute> attributes, @Nullable String eventField) {
88 super(modelFactory, node, container, attributes, eventField);
89 }
90
91 @Override
92 protected @Nullable ITmfStateSystemBuilder getStateSystem() {
93 return (ITmfStateSystemBuilder) super.getStateSystem();
94 }
95
96 @Override
97 protected TmfXmlStateValueBase initializeStateValue(ITmfXmlModelFactory modelFactory, Element node) {
98 TmfXmlStateValueBase stateValueType = null;
99 /* Process the XML Element state value */
100 String type = node.getAttribute(TmfXmlStrings.TYPE);
101 String value = getSsContainer().getAttributeValue(node.getAttribute(TmfXmlStrings.VALUE));
102
103 if (value == null && getStackType().equals(ValueTypeStack.NULL)) {
104 throw new IllegalStateException();
105 }
106
107 List<@Nullable Element> children = XmlUtils.getChildElements(node);
108 List<ITmfXmlStateAttribute> childAttributes = new ArrayList<>();
109 for (Element child : children) {
110 if (child == null) {
111 continue;
112 }
113 ITmfXmlStateAttribute queryAttribute = modelFactory.createStateAttribute(child, getSsContainer());
114 childAttributes.add(queryAttribute);
115 }
116
117 switch (type) {
118 case TmfXmlStrings.TYPE_INT: {
119 /* Integer value */
120 ITmfStateValue stateValue = value != null && !value.isEmpty() ?
121 TmfStateValue.newValueInt(Integer.parseInt(value)) : TmfStateValue.nullValue();
122 stateValueType = new TmfXmlStateValueTmf(stateValue, childAttributes);
123 break;
124 }
125 case TmfXmlStrings.TYPE_LONG: {
126 /* Long value */
127 ITmfStateValue stateValue = value != null && !value.isEmpty() ?
128 TmfStateValue.newValueLong(Long.parseLong(value)) : TmfStateValue.nullValue();
129 stateValueType = new TmfXmlStateValueTmf(stateValue, childAttributes);
130 break;
131 }
132 case TmfXmlStrings.TYPE_STRING: {
133 /* String value */
134 ITmfStateValue stateValue = value != null ?
135 TmfStateValue.newValueString(value) : TmfStateValue.nullValue();
136 stateValueType = new TmfXmlStateValueTmf(stateValue, childAttributes);
137 break;
138 }
139 case TmfXmlStrings.TYPE_NULL: {
140 /* Null value */
141 ITmfStateValue stateValue = TmfStateValue.nullValue();
142 stateValueType = new TmfXmlStateValueTmf(stateValue, childAttributes);
143 break;
144 }
145 case TmfXmlStrings.EVENT_FIELD:
146 /* Event field */
147 if (value == null) {
148 throw new IllegalStateException("Event field name cannot be null"); //$NON-NLS-1$
149 }
150 stateValueType = new TmfXmlStateValueEventField(value);
151 break;
152 case TmfXmlStrings.TYPE_EVENT_NAME:
153 /* The value is the event name */
154 stateValueType = new TmfXmlStateValueEventName();
155 break;
156 case TmfXmlStrings.TYPE_DELETE:
157 /* Deletes the value of an attribute */
158 stateValueType = new TmfXmlStateValueDelete();
159 break;
160 case TmfXmlStrings.TYPE_QUERY:
161 /* Value is the result of a query */
162 stateValueType = new TmfXmlStateValueQuery(childAttributes);
163 break;
164 default:
165 throw new IllegalArgumentException(String.format("TmfXmlStateValue constructor: unexpected element %s for stateValue type", type)); //$NON-NLS-1$
166 }
167 return stateValueType;
168 }
169
170 // ----------------------------------------------------------
171 // Internal state value classes for the different types
172 // ----------------------------------------------------------
173
174 /**
175 * Base class for all state value. Contain default methods to handle event,
176 * process or increment the value
177 */
178 protected abstract class TmfXmlStateValueTypeReadWrite extends TmfXmlStateValueBase {
179
180 @Override
181 public final void handleEvent(ITmfEvent event, int quark, long timestamp, @Nullable TmfXmlScenarioInfo scenarioInfo) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
182 if (isIncrement()) {
183 incrementValue(event, quark, timestamp, scenarioInfo);
184 } else {
185 ITmfStateValue value = getValue(event, scenarioInfo);
186 processValue(quark, timestamp, value);
187 }
188 }
189
190 @Override
191 protected void processValue(int quark, long timestamp, ITmfStateValue value) throws AttributeNotFoundException, TimeRangeException, StateValueTypeException {
192 ITmfStateSystemBuilder ss = getStateSystem();
193 if (ss == null) {
194 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
195 }
196 switch (getStackType()) {
197 case POP:
198 ss.popAttribute(timestamp, quark);
199 break;
200 case PUSH:
201 ss.pushAttribute(timestamp, value, quark);
202 break;
203 case NULL:
204 case PEEK:
205 default:
206 if (isUpdate()) {
207 ss.updateOngoingState(value, quark);
208 } else {
209 ss.modifyAttribute(timestamp, value, quark);
210 }
211 break;
212 }
213 }
214
215 @Override
216 protected void incrementValue(ITmfEvent event, int quark, long timestamp, @Nullable TmfXmlScenarioInfo scenarioInfo) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
217 ITmfStateSystemBuilder ss = getStateSystem();
218 if (ss == null) {
219 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
220 }
221 StateSystemBuilderUtils.incrementAttributeInt(ss, timestamp, quark, 1);
222 }
223 }
224
225 private static @Nullable ITmfStateValue incrementByType(int quark, ITmfStateSystem ss, ITmfStateValue stateValue) {
226 ITmfStateValue value = null;
227 switch (stateValue.getType()) {
228 case LONG: {
229 long incrementLong = stateValue.unboxLong();
230 ITmfStateValue currentState = ss.queryOngoingState(quark);
231 long currentValue = (currentState.isNull() ? 0 : currentState.unboxLong());
232 value = TmfStateValue.newValueLong(incrementLong + currentValue);
233 return value;
234 }
235 case INTEGER: {
236 int increment = stateValue.unboxInt();
237 ITmfStateValue currentState = ss.queryOngoingState(quark);
238 int currentValue = (currentState.isNull() ? 0 : currentState.unboxInt());
239 value = TmfStateValue.newValueInt(increment + currentValue);
240 return value;
241 }
242 case DOUBLE:
243 case NULL:
244 case STRING:
245 case CUSTOM:
246 default:
247 }
248 return value;
249 }
250
251 /* This state value uses a constant value, defined in the XML */
252 private class TmfXmlStateValueTmf extends TmfXmlStateValueTypeReadWrite {
253
254 private final ITmfStateValue fValue;
255 private final List<ITmfXmlStateAttribute> fAttributesValue;
256
257 public TmfXmlStateValueTmf(ITmfStateValue value, List<ITmfXmlStateAttribute> attributes) {
258 fValue = value;
259 fAttributesValue = attributes;
260 }
261
262 @Override
263 public ITmfStateValue getValue(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) {
264 try {
265 switch (getStackType()) {
266 case PEEK:
267 return peek(event, scenarioInfo);
268 case PUSH:
269 case NULL:
270 case POP:
271 default:
272 return fValue;
273 }
274 } catch (AttributeNotFoundException | StateSystemDisposedException e) {
275 Activator.logError("Query stack failed"); //$NON-NLS-1$
276 return TmfStateValue.nullValue();
277 }
278 }
279
280 /**
281 * @param event
282 * The ongoing event
283 * @param scenarioInfo
284 * The active scenario details. The value should be null if
285 * there no scenario.
286 * @return The value value at the top of the stack without removing it
287 * @throws AttributeNotFoundException
288 * If the do not exist
289 * @throws StateSystemDisposedException
290 * If the state system is disposed
291 */
292 private ITmfStateValue peek(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) throws AttributeNotFoundException, StateSystemDisposedException {
293 int quarkQuery = IXmlStateSystemContainer.ROOT_QUARK;
294 ITmfStateSystemBuilder ss = getStateSystem();
295 if (ss == null) {
296 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
297 }
298
299 if (event == null) {
300 throw new IllegalStateException("The event should not be null at this point."); //$NON-NLS-1$
301 }
302
303 for (ITmfXmlStateAttribute attribute : fAttributesValue) {
304 quarkQuery = attribute.getAttributeQuark(event, quarkQuery, scenarioInfo);
305 if (quarkQuery == IXmlStateSystemContainer.ERROR_QUARK) {
306 /*
307 * the query is not valid, we stop the state change
308 */
309 return TmfStateValue.nullValue();
310 }
311 }
312
313 final long ts = event.getTimestamp().toNanos();
314 @Nullable ITmfStateInterval stackTopInterval = StateSystemUtils.querySingleStackTop(ss, ts, quarkQuery);
315 final ITmfStateValue value = stackTopInterval != null ? stackTopInterval.getStateValue() : null;
316 return value != null ? value : TmfStateValue.nullValue();
317 }
318
319 @Override
320 public void incrementValue(ITmfEvent event, int quark, long timestamp, @Nullable TmfXmlScenarioInfo scenarioInfo) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
321 ITmfStateSystem ss = getStateSystem();
322 if (ss == null) {
323 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
324 }
325 ITmfStateValue value = incrementByType(quark, ss, fValue);
326 if (value != null) {
327 processValue(quark, timestamp, value);
328 } else {
329 Activator.logWarning("TmfXmlStateValue: The increment value is not a number type"); //$NON-NLS-1$
330 }
331 }
332
333 @Override
334 public String toString() {
335 return "Value=" + fValue; //$NON-NLS-1$
336 }
337
338 }
339
340 /* The state value uses the value of an event field */
341 private class TmfXmlStateValueEventField extends TmfXmlStateValueTypeReadWrite {
342
343 private final String fFieldName;
344
345 public TmfXmlStateValueEventField(String field) {
346 fFieldName = field;
347 }
348
349 @Override
350 public ITmfStateValue getValue(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) {
351 if (event == null) {
352 Activator.logWarning("XML State value: requested an event field, but event is null"); //$NON-NLS-1$
353 return TmfStateValue.nullValue();
354 }
355 return getEventFieldValue(event, fFieldName);
356 }
357
358 @Override
359 public void incrementValue(ITmfEvent event, int quark, long timestamp, @Nullable TmfXmlScenarioInfo scenarioInfo) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
360 ITmfStateSystem ss = getSsContainer().getStateSystem();
361 if (ss == null) {
362 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
363 }
364 ITmfStateValue incrementValue = getValue(event, scenarioInfo);
365 ITmfStateValue value = incrementByType(quark, ss, incrementValue);
366 if (value != null) {
367 processValue(quark, timestamp, value);
368 } else {
369 Activator.logWarning(String.format("TmfXmlStateValue: The event field increment %s is not a number type but a %s", fFieldName, incrementValue.getType())); //$NON-NLS-1$
370 }
371 }
372
373 @Override
374 public String toString() {
375 return "Event Field=" + fFieldName; //$NON-NLS-1$
376 }
377 }
378
379 /* The state value is the event name */
380 private class TmfXmlStateValueEventName extends TmfXmlStateValueTypeReadWrite {
381
382 @Override
383 public @NonNull ITmfStateValue getValue(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) throws AttributeNotFoundException {
384 if (event == null) {
385 Activator.logWarning("XML State value: request event name, but event is null"); //$NON-NLS-1$
386 return TmfStateValue.nullValue();
387 }
388 return TmfStateValue.newValueString(event.getName());
389 }
390
391 @Override
392 public String toString() {
393 return "Event name"; //$NON-NLS-1$
394 }
395 }
396
397 /* The state value deletes an attribute */
398 private class TmfXmlStateValueDelete extends TmfXmlStateValueTypeReadWrite {
399
400 @Override
401 public @NonNull ITmfStateValue getValue(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) throws AttributeNotFoundException {
402 return TmfStateValue.nullValue();
403 }
404
405 @Override
406 protected void processValue(int quark, long timestamp, ITmfStateValue value) throws TimeRangeException, AttributeNotFoundException {
407 ITmfStateSystem ss = getStateSystem();
408 if (!(ss instanceof ITmfStateSystemBuilder)) {
409 throw new IllegalStateException("incrementValue should never be called when not building the state system"); //$NON-NLS-1$
410 }
411 ITmfStateSystemBuilder builder = (ITmfStateSystemBuilder) ss;
412 builder.removeAttribute(timestamp, quark);
413 }
414
415 @Override
416 public String toString() {
417 return "Delete"; //$NON-NLS-1$
418 }
419 }
420
421 /* The state value uses the result of a query */
422 private class TmfXmlStateValueQuery extends TmfXmlStateValueTypeReadWrite {
423
424 private final List<ITmfXmlStateAttribute> fQueryValue;
425
426 public TmfXmlStateValueQuery(List<ITmfXmlStateAttribute> childAttributes) {
427 fQueryValue = childAttributes;
428 }
429
430 @Override
431 public ITmfStateValue getValue(@Nullable ITmfEvent event, @Nullable TmfXmlScenarioInfo scenarioInfo) throws AttributeNotFoundException {
432 /* Query the state system for the value */
433 ITmfStateValue value = TmfStateValue.nullValue();
434 int quarkQuery = IXmlStateSystemContainer.ROOT_QUARK;
435 ITmfStateSystem ss = getStateSystem();
436 if (ss == null) {
437 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
438 }
439
440 for (ITmfXmlStateAttribute attribute : fQueryValue) {
441 quarkQuery = attribute.getAttributeQuark(event, quarkQuery, scenarioInfo);
442 if (quarkQuery == IXmlStateSystemContainer.ERROR_QUARK) {
443 /* the query is not valid, we stop the state change */
444 break;
445 }
446 }
447 /*
448 * the query can fail : for example, if a value is requested but has
449 * not been set yet
450 */
451 if (quarkQuery != IXmlStateSystemContainer.ERROR_QUARK) {
452 value = ss.queryOngoingState(quarkQuery);
453 }
454 return value;
455 }
456
457 @Override
458 public void incrementValue(ITmfEvent event, int quark, long timestamp, @Nullable TmfXmlScenarioInfo scenarioInfo) throws StateValueTypeException, TimeRangeException, AttributeNotFoundException {
459 ITmfStateSystem ss = getStateSystem();
460 if (ss == null) {
461 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE);
462 }
463
464 ITmfStateValue incrementValue = getValue(event, scenarioInfo);
465 ITmfStateValue value = incrementByType(quark, ss, incrementValue);
466 if (value != null) {
467 processValue(quark, timestamp, value);
468 } else {
469 Activator.logWarning("TmfXmlStateValue: The query result increment is not a number type"); //$NON-NLS-1$
470 }
471 }
472
473 @Override
474 public String toString() {
475 return "Query=" + fQueryValue; //$NON-NLS-1$
476 }
477 }
478
479 }
This page took 0.051192 seconds and 6 git commands to generate.