tmf: Replace event matching API to use Collection
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.analysis.xml.core / src / org / eclipse / linuxtools / internal / tmf / analysis / xml / core / stateprovider / model / TmfXmlCondition.java
CommitLineData
0f7276b6
GB
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
13package org.eclipse.linuxtools.internal.tmf.analysis.xml.core.stateprovider.model;
14
15import java.util.ArrayList;
16import java.util.List;
17
18import org.eclipse.jdt.annotation.NonNull;
19import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils;
20import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
21import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.XmlStateProvider;
22import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
23import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
24import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder;
25import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
26import org.w3c.dom.Element;
27
28/**
29 * This Class implement a condition tree for a state change
30 *
31 * <pre>
32 * example:
33 * <and>
34 * <condition>
35 * <stateAttribute type="location" value="CurrentThread" />
36 * <stateAttribute type="constant" value="System_call" />
37 * <stateValue type="null" />
38 * </condition>
39 * <condition>
40 * </condition>
41 * </and>
42 * </pre>
43 *
44 * @author Florian Wininger
45 */
46public class TmfXmlCondition {
47
48 private final List<TmfXmlCondition> fConditions = new ArrayList<>();
49 private final TmfXmlStateValue fStateValue;
50 private final ConditionOperator fOperator;
51 private final XmlStateProvider fProvider;
52
53 private enum ConditionOperator {
54 NONE,
55 NOT,
56 AND,
57 OR,
58 }
59
60 /**
61 * Constructor
62 *
63 * @param node
64 * The XML root of this condition
65 * @param provider
66 * The state provider this condition belongs to
67 */
68 public TmfXmlCondition(Element node, XmlStateProvider provider) {
69 fProvider = provider;
70
71 Element rootNode = node;
72 /* Process the conditions: in each case, only process Element nodes */
73 List<Element> childElements = XmlUtils.getChildElements(rootNode);
74
75 /*
76 * If the node is an if, take the child as the root condition
77 *
78 * FIXME: Maybe the caller should do this instead.
79 */
80 if (node.getNodeName().equals(TmfXmlStrings.IF)) {
81 if (childElements.isEmpty()) {
82 throw new IllegalArgumentException("TmfXmlCondition constructor: IF node has no child element"); //$NON-NLS-1$
83 }
84 rootNode = childElements.get(0);
85 childElements = XmlUtils.getChildElements(rootNode);
86 }
87
88 switch (rootNode.getNodeName()) {
89 case TmfXmlStrings.CONDITION:
90 fOperator = ConditionOperator.NONE;
91 /* The last element is a state value node */
92 Element stateValueElement = childElements.remove(childElements.size() - 1);
93
94 /*
95 * A state value is either preceded by an eventField or a number of
96 * state attributes
97 */
98 if (childElements.size() == 1 && childElements.get(0).getNodeName().equals(TmfXmlStrings.ELEMENT_FIELD)) {
99 fStateValue = new TmfXmlStateValue(stateValueElement, fProvider, childElements.get(0).getAttribute(TmfXmlStrings.NAME));
100 } else {
101 List<TmfXmlStateAttribute> attributes = new ArrayList<>();
102 for (Element element : childElements) {
103 if (!element.getNodeName().equals(TmfXmlStrings.STATE_ATTRIBUTE)) {
104 throw new IllegalArgumentException("TmfXmlCondition: a condition either has a eventField element or a number of TmfXmlStateAttribute elements before the state value"); //$NON-NLS-1$
105 }
106 TmfXmlStateAttribute attribute = new TmfXmlStateAttribute(element, fProvider);
107 attributes.add(attribute);
108 }
109 fStateValue = new TmfXmlStateValue(stateValueElement, fProvider, attributes);
110 }
111 break;
112 case TmfXmlStrings.NOT:
113 fOperator = ConditionOperator.NOT;
114 fStateValue = null;
115 fConditions.add(new TmfXmlCondition(childElements.get(0), fProvider));
116 break;
117 case TmfXmlStrings.AND:
118 fOperator = ConditionOperator.AND;
119 fStateValue = null;
120 for (Element condition : childElements) {
121 fConditions.add(new TmfXmlCondition(condition, fProvider));
122 }
123 break;
124 case TmfXmlStrings.OR:
125 fOperator = ConditionOperator.OR;
126 fStateValue = null;
127 for (Element condition : childElements) {
128 fConditions.add(new TmfXmlCondition(condition, fProvider));
129 }
130 break;
131 default:
132 throw new IllegalArgumentException("TmfXmlCondition constructor: XML node is of the wrong type"); //$NON-NLS-1$
133 }
134 }
135
136 /**
137 * Test the result of the condition for an event
138 *
139 * @param event
140 * The event on which to test the condition
141 * @return Whether the condition is true or not
142 * @throws AttributeNotFoundException
143 * The state attribute was not found
144 */
145 public boolean testForEvent(@NonNull ITmfEvent event) throws AttributeNotFoundException {
146 ITmfStateSystemBuilder ss = fProvider.getAssignedStateSystem();
147 /*
148 * The condition is either the equality check of a state value or a
149 * boolean operation on other conditions
150 */
151 if (fStateValue != null) {
152 TmfXmlStateValue filter = fStateValue;
153 int quark = XmlStateProvider.ROOT_QUARK;
154 for (TmfXmlStateAttribute attribute : filter.getAttributes()) {
155 quark = attribute.getAttributeQuark(event, quark);
156 /*
157 * When verifying a condition, the state attribute must exist,
158 * if it does not, the query is not valid, we stop the condition
159 * check
160 */
161 if (quark == XmlStateProvider.ERROR_QUARK) {
162 throw new AttributeNotFoundException();
163 }
164 }
165
166 /* Get the value to compare to from the XML file */
167 ITmfStateValue valueXML;
168 valueXML = filter.getValue(event);
169
170 /*
171 * The actual value: it can be either queried in the state system or
172 * found in the event
173 */
174 ITmfStateValue valueState = (quark != XmlStateProvider.ROOT_QUARK) ? ss.queryOngoingState(quark) :
175 filter.getEventField(event);
176
177 return valueXML.equals(valueState);
178
179 } else if (!fConditions.isEmpty()) {
180 /* Verify a condition tree */
181 switch (fOperator) {
182 case AND:
183 for (TmfXmlCondition childCondition : fConditions) {
184 if (!childCondition.testForEvent(event)) {
185 return false;
186 }
187 }
188 return true;
189 case NONE:
190 break;
191 case NOT:
192 return !fConditions.get(0).testForEvent(event);
193 case OR:
194 for (TmfXmlCondition childCondition : fConditions) {
195 if (childCondition.testForEvent(event)) {
196 return true;
197 }
198 }
199 return false;
200 default:
201 break;
202
203 }
204 } else {
205 throw new IllegalStateException("TmfXmlCondition: the condition should be either a state value or be the result of a condition tree"); //$NON-NLS-1$
206 }
207 return true;
208 }
209
210}
This page took 0.032453 seconds and 5 git commands to generate.