1 /*******************************************************************************
2 * Copyright (c) 2014 Ecole Polytechnique de Montreal
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 * Florian Wininger - Initial API and implementation
11 ******************************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.model
;
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
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
23 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
24 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.XmlUtils
;
25 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
27 import org
.w3c
.dom
.Element
;
28 import org
.w3c
.dom
.Node
;
31 * This Class implement a State Change in the XML-defined state system
34 * example 1: Simple state change
36 * <stateAttribute type="location" value="CurrentThread" />
37 * <stateAttribute type="constant" value="System_call" />
38 * <stateValue type="null" />
41 * example 2: Conditional state change
45 * <stateAttribute type="location" value="CurrentThread" />
46 * <stateAttribute type="constant" value="System_call" />
47 * <stateValue type="null" />
51 * <stateAttribute type="location" value="CurrentThread" />
52 * <stateAttribute type="constant" value="Status" />
53 * <stateValue int="$PROCESS_STATUS_RUN_USERMODE"/>
56 * <stateAttribute type="location" value="CurrentThread" />
57 * <stateAttribute type="constant" value="Status" />
58 * <stateValue int="$PROCESS_STATUS_RUN_SYSCALL"/>
63 * @author Florian Wininger
65 public class TmfXmlStateChange
{
67 private final IXmlStateChange fChange
;
68 private final IXmlStateSystemContainer fContainer
;
74 * The factory used to create XML model elements
76 * XML node root of this state change
78 * The state system container this state change belongs to
80 public TmfXmlStateChange(ITmfXmlModelFactory modelFactory
, Element statechange
, IXmlStateSystemContainer container
) {
81 fContainer
= container
;
84 * child nodes is either a list of TmfXmlStateAttributes and
85 * TmfXmlStateValues, or an if-then-else series of nodes.
87 Node ifNode
= statechange
.getElementsByTagName(TmfXmlStrings
.IF
).item(0);
89 /* the state change has a condition */
90 fChange
= new XmlConditionalChange(modelFactory
, statechange
);
92 /* the state change does not have a condition */
93 fChange
= new XmlStateValueChange(modelFactory
, statechange
);
98 * Execute the state change for an event. If necessary, it validates the
99 * condition and executes the required change.
102 * The event to process
103 * @param scenarioInfo
104 * The active scenario details. The value should be null if there
106 * @throws AttributeNotFoundException
107 * Pass through the exception it received
108 * @throws TimeRangeException
109 * Pass through the exception it received
110 * @throws StateValueTypeException
111 * Pass through the exception it received
114 public void handleEvent(ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws AttributeNotFoundException
, StateValueTypeException
, TimeRangeException
{
115 fChange
.handleEvent(event
, scenarioInfo
);
119 public String
toString() {
120 return "TmfXmlStateChange: " + fChange
; //$NON-NLS-1$
123 /* Interface for both private classes to handle the event */
124 private interface IXmlStateChange
{
125 void handleEvent(ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws AttributeNotFoundException
, StateValueTypeException
, TimeRangeException
;
129 * Conditional state change with a condition to verify
131 private class XmlConditionalChange
implements IXmlStateChange
{
132 private final TmfXmlCondition fCondition
;
133 private final TmfXmlStateChange fThenChange
;
134 private final @Nullable TmfXmlStateChange fElseChange
;
136 public XmlConditionalChange(ITmfXmlModelFactory modelFactory
, Element statechange
) {
138 * The if node exists, it has been verified before calling this
140 Node ifNode
= statechange
.getElementsByTagName(TmfXmlStrings
.IF
).item(0);
141 if (ifNode
== null) {
142 throw new IllegalArgumentException();
144 fCondition
= modelFactory
.createCondition((Element
) ifNode
, fContainer
);
146 Node thenNode
= statechange
.getElementsByTagName(TmfXmlStrings
.THEN
).item(0);
147 if (thenNode
== null) {
148 throw new IllegalArgumentException("Conditional state change: there should be a then clause."); //$NON-NLS-1$
150 fThenChange
= modelFactory
.createStateChange((Element
) thenNode
, fContainer
);
152 Node elseNode
= statechange
.getElementsByTagName(TmfXmlStrings
.ELSE
).item(0);
153 if (elseNode
!= null) {
154 fElseChange
= modelFactory
.createStateChange((Element
) elseNode
, fContainer
);
161 public void handleEvent(@NonNull ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws AttributeNotFoundException
, StateValueTypeException
, TimeRangeException
{
162 TmfXmlStateChange toExecute
= fThenChange
;
164 if (!fCondition
.testForEvent(event
, scenarioInfo
)) {
165 toExecute
= fElseChange
;
167 } catch (AttributeNotFoundException e
) {
169 * An attribute in the condition did not exist (yet), return
170 * from the state change
175 if (toExecute
== null) {
178 toExecute
.handleEvent(event
, scenarioInfo
);
182 public String
toString() {
183 return "Condition: " + fCondition
; //$NON-NLS-1$
188 * State change with no condition
190 private class XmlStateValueChange
implements IXmlStateChange
{
191 private final ITmfXmlStateValue fValue
;
193 public XmlStateValueChange(ITmfXmlModelFactory modelFactory
, Element statechange
) {
194 List
<@Nullable Element
> childElements
= XmlUtils
.getChildElements(statechange
);
197 * Last child element is the state value, the others are attributes
198 * to reach to value to set
200 Element stateValueElement
= childElements
.remove(childElements
.size() - 1);
201 if (stateValueElement
== null) {
202 throw new IllegalStateException();
204 List
<ITmfXmlStateAttribute
> attributes
= new ArrayList
<>();
205 for (Element element
: childElements
) {
206 if (element
== null || !element
.getNodeName().equals(TmfXmlStrings
.STATE_ATTRIBUTE
)) {
207 throw new IllegalArgumentException("TmfXmlStateChange: a state change must have only TmfXmlStateAttribute elements before the state value"); //$NON-NLS-1$
209 ITmfXmlStateAttribute attribute
= modelFactory
.createStateAttribute(element
, fContainer
);
210 attributes
.add(attribute
);
212 if (attributes
.isEmpty()) {
213 throw new IllegalArgumentException("TmfXmlStateChange: a state change must have at least one TmfXmlStateAttribute element before the state value"); //$NON-NLS-1$
215 fValue
= modelFactory
.createStateValue(stateValueElement
, fContainer
, attributes
);
219 public void handleEvent(@NonNull ITmfEvent event
, @Nullable TmfXmlScenarioInfo scenarioInfo
) throws AttributeNotFoundException
, StateValueTypeException
, TimeRangeException
{
220 fValue
.handleEvent(event
, scenarioInfo
);
224 public String
toString() {
225 return "Value: " + fValue
; //$NON-NLS-1$