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
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
21 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
22 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.IXmlStateSystemContainer
;
23 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.module
.XmlUtils
;
24 import org
.eclipse
.tracecompass
.tmf
.analysis
.xml
.core
.stateprovider
.TmfXmlStrings
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
26 import org
.w3c
.dom
.Element
;
29 * This Class implement a condition tree in the XML-defined state system.
35 * <stateAttribute type="location" value="CurrentThread" />
36 * <stateAttribute type="constant" value="System_call" />
37 * <stateValue type="null" />
44 * @author Florian Wininger
46 public class TmfXmlCondition
{
48 private final List
<TmfXmlCondition
> fConditions
= new ArrayList
<>();
49 private final ITmfXmlStateValue fStateValue
;
50 private final ConditionOperator fOperator
;
51 private final IXmlStateSystemContainer fContainer
;
53 private enum ConditionOperator
{
64 * The factory used to create XML model elements
66 * The XML root of this condition
68 * The state system container this condition belongs to
70 public TmfXmlCondition(ITmfXmlModelFactory modelFactory
, Element node
, IXmlStateSystemContainer container
) {
71 fContainer
= container
;
73 Element rootNode
= node
;
74 /* Process the conditions: in each case, only process Element nodes */
75 List
<Element
> childElements
= XmlUtils
.getChildElements(rootNode
);
78 * If the node is an if, take the child as the root condition
80 * FIXME: Maybe the caller should do this instead.
82 if (node
.getNodeName().equals(TmfXmlStrings
.IF
)) {
83 if (childElements
.isEmpty()) {
84 throw new IllegalArgumentException("TmfXmlCondition constructor: IF node has no child element"); //$NON-NLS-1$
86 rootNode
= childElements
.get(0);
87 childElements
= XmlUtils
.getChildElements(rootNode
);
90 switch (rootNode
.getNodeName()) {
91 case TmfXmlStrings
.CONDITION
:
92 fOperator
= ConditionOperator
.NONE
;
93 /* The last element is a state value node */
94 Element stateValueElement
= childElements
.remove(childElements
.size() - 1);
97 * A state value is either preceded by an eventField or a number of
100 if (childElements
.size() == 1 && childElements
.get(0).getNodeName().equals(TmfXmlStrings
.ELEMENT_FIELD
)) {
101 fStateValue
= modelFactory
.createStateValue(stateValueElement
, fContainer
, childElements
.get(0).getAttribute(TmfXmlStrings
.NAME
));
103 List
<ITmfXmlStateAttribute
> attributes
= new ArrayList
<>();
104 for (Element element
: childElements
) {
105 if (!element
.getNodeName().equals(TmfXmlStrings
.STATE_ATTRIBUTE
)) {
106 throw new IllegalArgumentException("TmfXmlCondition: a condition either has a eventField element or a number of TmfXmlStateAttribute elements before the state value"); //$NON-NLS-1$
108 ITmfXmlStateAttribute attribute
= modelFactory
.createStateAttribute(element
, fContainer
);
109 attributes
.add(attribute
);
111 fStateValue
= modelFactory
.createStateValue(stateValueElement
, fContainer
, attributes
);
114 case TmfXmlStrings
.NOT
:
115 fOperator
= ConditionOperator
.NOT
;
117 fConditions
.add(modelFactory
.createCondition(childElements
.get(0), fContainer
));
119 case TmfXmlStrings
.AND
:
120 fOperator
= ConditionOperator
.AND
;
122 for (Element condition
: childElements
) {
123 fConditions
.add(modelFactory
.createCondition(condition
, fContainer
));
126 case TmfXmlStrings
.OR
:
127 fOperator
= ConditionOperator
.OR
;
129 for (Element condition
: childElements
) {
130 fConditions
.add(modelFactory
.createCondition(condition
, fContainer
));
134 throw new IllegalArgumentException("TmfXmlCondition constructor: XML node is of the wrong type"); //$NON-NLS-1$
139 * Test the result of the condition for an event
142 * The event on which to test the condition
143 * @return Whether the condition is true or not
144 * @throws AttributeNotFoundException
145 * The state attribute was not found
147 public boolean testForEvent(@NonNull ITmfEvent event
) throws AttributeNotFoundException
{
148 ITmfStateSystem ss
= fContainer
.getStateSystem();
150 * The condition is either the equality check of a state value or a
151 * boolean operation on other conditions
153 if (fStateValue
!= null) {
154 ITmfXmlStateValue filter
= fStateValue
;
155 int quark
= IXmlStateSystemContainer
.ROOT_QUARK
;
156 for (ITmfXmlStateAttribute attribute
: filter
.getAttributes()) {
157 quark
= attribute
.getAttributeQuark(event
, quark
);
159 * When verifying a condition, the state attribute must exist,
160 * if it does not, the query is not valid, we stop the condition
163 if (quark
== IXmlStateSystemContainer
.ERROR_QUARK
) {
164 throw new AttributeNotFoundException();
168 /* Get the value to compare to from the XML file */
169 ITmfStateValue valueXML
;
170 valueXML
= filter
.getValue(event
);
173 * The actual value: it can be either queried in the state system or
176 ITmfStateValue valueState
= (quark
!= IXmlStateSystemContainer
.ROOT_QUARK
) ? ss
.queryOngoingState(quark
) :
177 filter
.getEventFieldValue(event
);
179 return valueXML
.equals(valueState
);
181 } else if (!fConditions
.isEmpty()) {
182 /* Verify a condition tree */
185 for (TmfXmlCondition childCondition
: fConditions
) {
186 if (!childCondition
.testForEvent(event
)) {
194 return !fConditions
.get(0).testForEvent(event
);
196 for (TmfXmlCondition childCondition
: fConditions
) {
197 if (childCondition
.testForEvent(event
)) {
207 throw new IllegalStateException("TmfXmlCondition: the condition should be either a state value or be the result of a condition tree"); //$NON-NLS-1$
213 public String
toString() {
214 return "TmfXmlCondition: " + fOperator
+ " on " + fConditions
; //$NON-NLS-1$ //$NON-NLS-2$