1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.model
.readwrite
;
15 import java
.util
.ArrayList
;
16 import java
.util
.List
;
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
;
43 * Implements a state value in a read write mode. See {@link TmfXmlStateValue}
44 * for the syntax of the state value.
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
49 * @author Geneviève Bastien
51 public class TmfXmlReadWriteStateValue
extends TmfXmlStateValue
{
53 private static final String ILLEGAL_STATE_EXCEPTION_MESSAGE
= "The state system hasn't been initialized yet"; //$NON-NLS-1$
56 * Constructor where the path to the value is a list of state attributes
59 * The factory used to create XML model elements
61 * The state value XML element
63 * The state system container this state value belongs to
65 * The attributes representing the path to this value
67 public TmfXmlReadWriteStateValue(TmfXmlReadWriteModelFactory modelFactory
, Element node
, IXmlStateSystemContainer container
, List
<ITmfXmlStateAttribute
> attributes
) {
68 this(modelFactory
, node
, container
, attributes
, null);
72 * Constructor where the path to the value is an event field
75 * The factory used to create XML model elements
77 * The state value XML element
79 * The state system container this state value belongs to
81 * The event field where to get the value
83 public TmfXmlReadWriteStateValue(TmfXmlReadWriteModelFactory modelFactory
, Element node
, IXmlStateSystemContainer container
, String eventField
) {
84 this(modelFactory
, node
, container
, new ArrayList
<ITmfXmlStateAttribute
>(), eventField
);
87 private TmfXmlReadWriteStateValue(ITmfXmlModelFactory modelFactory
, Element node
, IXmlStateSystemContainer container
, List
<ITmfXmlStateAttribute
> attributes
, @Nullable String eventField
) {
88 super(modelFactory
, node
, container
, attributes
, eventField
);
92 protected @Nullable ITmfStateSystemBuilder
getStateSystem() {
93 return (ITmfStateSystemBuilder
) super.getStateSystem();
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
));
103 if (value
== null && getStackType().equals(ValueTypeStack
.NULL
)) {
104 throw new IllegalStateException();
107 List
<@Nullable Element
> children
= XmlUtils
.getChildElements(node
);
108 List
<ITmfXmlStateAttribute
> childAttributes
= new ArrayList
<>();
109 for (Element child
: children
) {
113 ITmfXmlStateAttribute queryAttribute
= modelFactory
.createStateAttribute(child
, getSsContainer());
114 childAttributes
.add(queryAttribute
);
118 case TmfXmlStrings
.TYPE_INT
: {
120 ITmfStateValue stateValue
= value
!= null && !value
.isEmpty() ?
121 TmfStateValue
.newValueInt(Integer
.parseInt(value
)) : TmfStateValue
.nullValue();
122 stateValueType
= new TmfXmlStateValueTmf(stateValue
, childAttributes
);
125 case TmfXmlStrings
.TYPE_LONG
: {
127 ITmfStateValue stateValue
= value
!= null && !value
.isEmpty() ?
128 TmfStateValue
.newValueLong(Long
.parseLong(value
)) : TmfStateValue
.nullValue();
129 stateValueType
= new TmfXmlStateValueTmf(stateValue
, childAttributes
);
132 case TmfXmlStrings
.TYPE_STRING
: {
134 ITmfStateValue stateValue
= value
!= null ?
135 TmfStateValue
.newValueString(value
) : TmfStateValue
.nullValue();
136 stateValueType
= new TmfXmlStateValueTmf(stateValue
, childAttributes
);
139 case TmfXmlStrings
.TYPE_NULL
: {
141 ITmfStateValue stateValue
= TmfStateValue
.nullValue();
142 stateValueType
= new TmfXmlStateValueTmf(stateValue
, childAttributes
);
145 case TmfXmlStrings
.EVENT_FIELD
:
148 throw new IllegalStateException("Event field name cannot be null"); //$NON-NLS-1$
150 stateValueType
= new TmfXmlStateValueEventField(value
);
152 case TmfXmlStrings
.TYPE_EVENT_NAME
:
153 /* The value is the event name */
154 stateValueType
= new TmfXmlStateValueEventName();
156 case TmfXmlStrings
.TYPE_DELETE
:
157 /* Deletes the value of an attribute */
158 stateValueType
= new TmfXmlStateValueDelete();
160 case TmfXmlStrings
.TYPE_QUERY
:
161 /* Value is the result of a query */
162 stateValueType
= new TmfXmlStateValueQuery(childAttributes
);
165 throw new IllegalArgumentException(String
.format("TmfXmlStateValue constructor: unexpected element %s for stateValue type", type
)); //$NON-NLS-1$
167 return stateValueType
;
170 // ----------------------------------------------------------
171 // Internal state value classes for the different types
172 // ----------------------------------------------------------
175 * Base class for all state value. Contain default methods to handle event,
176 * process or increment the value
178 protected abstract class TmfXmlStateValueTypeReadWrite
extends TmfXmlStateValueBase
{
181 public final void handleEvent(ITmfEvent event
, int quark
, long timestamp
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws StateValueTypeException
, TimeRangeException
, AttributeNotFoundException
{
183 incrementValue(event
, quark
, timestamp
, scenarioInfo
);
185 ITmfStateValue value
= getValue(event
, scenarioInfo
);
186 processValue(quark
, timestamp
, value
);
191 protected void processValue(int quark
, long timestamp
, ITmfStateValue value
) throws AttributeNotFoundException
, TimeRangeException
, StateValueTypeException
{
192 ITmfStateSystemBuilder ss
= getStateSystem();
194 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE
);
196 switch (getStackType()) {
198 ss
.popAttribute(timestamp
, quark
);
201 ss
.pushAttribute(timestamp
, value
, quark
);
207 ss
.updateOngoingState(value
, quark
);
209 ss
.modifyAttribute(timestamp
, value
, quark
);
216 protected void incrementValue(ITmfEvent event
, int quark
, long timestamp
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws StateValueTypeException
, TimeRangeException
, AttributeNotFoundException
{
217 ITmfStateSystemBuilder ss
= getStateSystem();
219 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE
);
221 StateSystemBuilderUtils
.incrementAttributeInt(ss
, timestamp
, quark
, 1);
225 private static @Nullable ITmfStateValue
incrementByType(int quark
, ITmfStateSystem ss
, ITmfStateValue stateValue
) {
226 ITmfStateValue value
= null;
227 switch (stateValue
.getType()) {
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
);
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
);
251 /* This state value uses a constant value, defined in the XML */
252 private class TmfXmlStateValueTmf
extends TmfXmlStateValueTypeReadWrite
{
254 private final ITmfStateValue fValue
;
255 private final List
<ITmfXmlStateAttribute
> fAttributesValue
;
257 public TmfXmlStateValueTmf(ITmfStateValue value
, List
<ITmfXmlStateAttribute
> attributes
) {
259 fAttributesValue
= attributes
;
263 public ITmfStateValue
getValue(@Nullable ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
265 switch (getStackType()) {
267 return peek(event
, scenarioInfo
);
274 } catch (AttributeNotFoundException
| StateSystemDisposedException e
) {
275 Activator
.logError("Query stack failed"); //$NON-NLS-1$
276 return TmfStateValue
.nullValue();
283 * @param scenarioInfo
284 * The active scenario details. The value should be null if
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
292 private ITmfStateValue
peek(@Nullable ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws AttributeNotFoundException
, StateSystemDisposedException
{
293 int quarkQuery
= IXmlStateSystemContainer
.ROOT_QUARK
;
294 ITmfStateSystemBuilder ss
= getStateSystem();
296 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE
);
300 throw new IllegalStateException("The event should not be null at this point."); //$NON-NLS-1$
303 for (ITmfXmlStateAttribute attribute
: fAttributesValue
) {
304 quarkQuery
= attribute
.getAttributeQuark(event
, quarkQuery
, scenarioInfo
);
305 if (quarkQuery
== IXmlStateSystemContainer
.ERROR_QUARK
) {
307 * the query is not valid, we stop the state change
309 return TmfStateValue
.nullValue();
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();
320 public void incrementValue(ITmfEvent event
, int quark
, long timestamp
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws StateValueTypeException
, TimeRangeException
, AttributeNotFoundException
{
321 ITmfStateSystem ss
= getStateSystem();
323 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE
);
325 ITmfStateValue value
= incrementByType(quark
, ss
, fValue
);
327 processValue(quark
, timestamp
, value
);
329 Activator
.logWarning("TmfXmlStateValue: The increment value is not a number type"); //$NON-NLS-1$
334 public String
toString() {
335 return "Value=" + fValue
; //$NON-NLS-1$
340 /* The state value uses the value of an event field */
341 private class TmfXmlStateValueEventField
extends TmfXmlStateValueTypeReadWrite
{
343 private final String fFieldName
;
345 public TmfXmlStateValueEventField(String field
) {
350 public ITmfStateValue
getValue(@Nullable ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) {
352 Activator
.logWarning("XML State value: requested an event field, but event is null"); //$NON-NLS-1$
353 return TmfStateValue
.nullValue();
355 return getEventFieldValue(event
, fFieldName
);
359 public void incrementValue(ITmfEvent event
, int quark
, long timestamp
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws StateValueTypeException
, TimeRangeException
, AttributeNotFoundException
{
360 ITmfStateSystem ss
= getSsContainer().getStateSystem();
362 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE
);
364 ITmfStateValue incrementValue
= getValue(event
, scenarioInfo
);
365 ITmfStateValue value
= incrementByType(quark
, ss
, incrementValue
);
367 processValue(quark
, timestamp
, value
);
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$
374 public String
toString() {
375 return "Event Field=" + fFieldName
; //$NON-NLS-1$
379 /* The state value is the event name */
380 private class TmfXmlStateValueEventName
extends TmfXmlStateValueTypeReadWrite
{
383 public @NonNull ITmfStateValue
getValue(@Nullable ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws AttributeNotFoundException
{
385 Activator
.logWarning("XML State value: request event name, but event is null"); //$NON-NLS-1$
386 return TmfStateValue
.nullValue();
388 return TmfStateValue
.newValueString(event
.getName());
392 public String
toString() {
393 return "Event name"; //$NON-NLS-1$
397 /* The state value deletes an attribute */
398 private class TmfXmlStateValueDelete
extends TmfXmlStateValueTypeReadWrite
{
401 public @NonNull ITmfStateValue
getValue(@Nullable ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws AttributeNotFoundException
{
402 return TmfStateValue
.nullValue();
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$
411 ITmfStateSystemBuilder builder
= (ITmfStateSystemBuilder
) ss
;
412 builder
.removeAttribute(timestamp
, quark
);
416 public String
toString() {
417 return "Delete"; //$NON-NLS-1$
421 /* The state value uses the result of a query */
422 private class TmfXmlStateValueQuery
extends TmfXmlStateValueTypeReadWrite
{
424 private final List
<ITmfXmlStateAttribute
> fQueryValue
;
426 public TmfXmlStateValueQuery(List
<ITmfXmlStateAttribute
> childAttributes
) {
427 fQueryValue
= childAttributes
;
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();
437 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE
);
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 */
448 * the query can fail : for example, if a value is requested but has
451 if (quarkQuery
!= IXmlStateSystemContainer
.ERROR_QUARK
) {
452 value
= ss
.queryOngoingState(quarkQuery
);
458 public void incrementValue(ITmfEvent event
, int quark
, long timestamp
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws StateValueTypeException
, TimeRangeException
, AttributeNotFoundException
{
459 ITmfStateSystem ss
= getStateSystem();
461 throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_MESSAGE
);
464 ITmfStateValue incrementValue
= getValue(event
, scenarioInfo
);
465 ITmfStateValue value
= incrementByType(quark
, ss
, incrementValue
);
467 processValue(quark
, timestamp
, value
);
469 Activator
.logWarning("TmfXmlStateValue: The query result increment is not a number type"); //$NON-NLS-1$
474 public String
toString() {
475 return "Query=" + fQueryValue
; //$NON-NLS-1$