Add null checks for methods missing them
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.core / src / org / eclipse / tracecompass / tmf / analysis / xml / core / model / TmfXmlCondition.java
CommitLineData
0f7276b6 1/*******************************************************************************
e13bd4cd 2 * Copyright (c) 2014, 2015 Ecole Polytechnique de Montreal
0f7276b6
GB
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
5ddeee68 11 * Naser Ezzati - Add the comparison operators
e13bd4cd 12 * Patrick Tasse - Add message to exceptions
0f7276b6
GB
13 ******************************************************************************/
14
2bdf0193 15package org.eclipse.tracecompass.tmf.analysis.xml.core.model;
0f7276b6
GB
16
17import java.util.ArrayList;
18import java.util.List;
19
12685851 20import org.eclipse.jdt.annotation.Nullable;
e894a508
AM
21import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
22import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
23import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
2bdf0193
AM
24import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
25import org.eclipse.tracecompass.tmf.analysis.xml.core.module.XmlUtils;
26import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
27import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
0f7276b6
GB
28import org.w3c.dom.Element;
29
30/**
1d7e62f9 31 * This Class implement a condition tree in the XML-defined state system.
0f7276b6
GB
32 *
33 * <pre>
34 * example:
35 * <and>
36 * <condition>
37 * <stateAttribute type="location" value="CurrentThread" />
38 * <stateAttribute type="constant" value="System_call" />
39 * <stateValue type="null" />
40 * </condition>
41 * <condition>
42 * </condition>
43 * </and>
44 * </pre>
45 *
46 * @author Florian Wininger
47 */
48public class TmfXmlCondition {
49
50 private final List<TmfXmlCondition> fConditions = new ArrayList<>();
12685851 51 private final @Nullable ITmfXmlStateValue fStateValue;
5ddeee68 52 private final LogicalOperator fOperator;
1d7e62f9 53 private final IXmlStateSystemContainer fContainer;
5ddeee68 54 private final ConditionOperator fConditionOperator;
0f7276b6 55
5ddeee68 56 private enum LogicalOperator {
0f7276b6
GB
57 NONE,
58 NOT,
59 AND,
60 OR,
61 }
62
5ddeee68
NE
63 private enum ConditionOperator {
64 NONE,
65 EQ,
66 NE,
67 GE,
68 GT,
69 LE,
70 LT
71 }
72
0f7276b6
GB
73 /**
74 * Constructor
75 *
1d7e62f9
GB
76 * @param modelFactory
77 * The factory used to create XML model elements
0f7276b6
GB
78 * @param node
79 * The XML root of this condition
1d7e62f9
GB
80 * @param container
81 * The state system container this condition belongs to
0f7276b6 82 */
1d7e62f9
GB
83 public TmfXmlCondition(ITmfXmlModelFactory modelFactory, Element node, IXmlStateSystemContainer container) {
84 fContainer = container;
0f7276b6
GB
85
86 Element rootNode = node;
87 /* Process the conditions: in each case, only process Element nodes */
88 List<Element> childElements = XmlUtils.getChildElements(rootNode);
89
90 /*
91 * If the node is an if, take the child as the root condition
92 *
93 * FIXME: Maybe the caller should do this instead.
94 */
95 if (node.getNodeName().equals(TmfXmlStrings.IF)) {
96 if (childElements.isEmpty()) {
97 throw new IllegalArgumentException("TmfXmlCondition constructor: IF node has no child element"); //$NON-NLS-1$
98 }
99 rootNode = childElements.get(0);
100 childElements = XmlUtils.getChildElements(rootNode);
101 }
102
103 switch (rootNode.getNodeName()) {
104 case TmfXmlStrings.CONDITION:
5ddeee68
NE
105 fOperator = LogicalOperator.NONE;
106 /* Read comparison type */
107 String equationType = rootNode.getAttribute(TmfXmlStrings.OPERATOR);
108
109 switch (equationType) {
110 case TmfXmlStrings.EQ:
111 fConditionOperator = ConditionOperator.EQ;
112 break;
113 case TmfXmlStrings.NE:
114 fConditionOperator = ConditionOperator.NE;
115 break;
116 case TmfXmlStrings.GE:
117 fConditionOperator = ConditionOperator.GE;
118 break;
119 case TmfXmlStrings.GT:
120 fConditionOperator = ConditionOperator.GT;
121 break;
122 case TmfXmlStrings.LE:
123 fConditionOperator = ConditionOperator.LE;
124 break;
125 case TmfXmlStrings.LT:
126 fConditionOperator = ConditionOperator.LT;
127 break;
128 case TmfXmlStrings.NULL:
129 fConditionOperator = ConditionOperator.EQ;
130 break;
131 default:
132 throw new IllegalArgumentException("TmfXmlCondition: invalid comparison operator."); //$NON-NLS-1$
133 }
0f7276b6
GB
134 /* The last element is a state value node */
135 Element stateValueElement = childElements.remove(childElements.size() - 1);
12685851
GB
136 if (stateValueElement == null) {
137 throw new IllegalStateException();
138 }
0f7276b6
GB
139
140 /*
141 * A state value is either preceded by an eventField or a number of
142 * state attributes
143 */
144 if (childElements.size() == 1 && childElements.get(0).getNodeName().equals(TmfXmlStrings.ELEMENT_FIELD)) {
12685851
GB
145 String attribute = childElements.get(0).getAttribute(TmfXmlStrings.NAME);
146 if (attribute == null) {
147 throw new IllegalArgumentException();
148 }
149 fStateValue = modelFactory.createStateValue(stateValueElement, fContainer, attribute);
0f7276b6 150 } else {
1d7e62f9 151 List<ITmfXmlStateAttribute> attributes = new ArrayList<>();
0f7276b6
GB
152 for (Element element : childElements) {
153 if (!element.getNodeName().equals(TmfXmlStrings.STATE_ATTRIBUTE)) {
154 throw new IllegalArgumentException("TmfXmlCondition: a condition either has a eventField element or a number of TmfXmlStateAttribute elements before the state value"); //$NON-NLS-1$
155 }
1d7e62f9 156 ITmfXmlStateAttribute attribute = modelFactory.createStateAttribute(element, fContainer);
0f7276b6
GB
157 attributes.add(attribute);
158 }
1d7e62f9 159 fStateValue = modelFactory.createStateValue(stateValueElement, fContainer, attributes);
0f7276b6
GB
160 }
161 break;
162 case TmfXmlStrings.NOT:
5ddeee68 163 fOperator = LogicalOperator.NOT;
0f7276b6 164 fStateValue = null;
5ddeee68 165 fConditionOperator = ConditionOperator.NONE;
12685851
GB
166 Element element = childElements.get(0);
167 if (element == null) {
168 throw new IllegalArgumentException();
169 }
170 fConditions.add(modelFactory.createCondition(element, fContainer));
0f7276b6
GB
171 break;
172 case TmfXmlStrings.AND:
5ddeee68 173 fOperator = LogicalOperator.AND;
0f7276b6 174 fStateValue = null;
5ddeee68 175 fConditionOperator = ConditionOperator.NONE;
0f7276b6 176 for (Element condition : childElements) {
12685851
GB
177 if (condition == null) {
178 continue;
179 }
1d7e62f9 180 fConditions.add(modelFactory.createCondition(condition, fContainer));
0f7276b6
GB
181 }
182 break;
183 case TmfXmlStrings.OR:
5ddeee68 184 fOperator = LogicalOperator.OR;
0f7276b6 185 fStateValue = null;
5ddeee68 186 fConditionOperator = ConditionOperator.NONE;
0f7276b6 187 for (Element condition : childElements) {
12685851
GB
188 if (condition == null) {
189 continue;
190 }
1d7e62f9 191 fConditions.add(modelFactory.createCondition(condition, fContainer));
0f7276b6
GB
192 }
193 break;
194 default:
195 throw new IllegalArgumentException("TmfXmlCondition constructor: XML node is of the wrong type"); //$NON-NLS-1$
196 }
197 }
198
199 /**
200 * Test the result of the condition for an event
201 *
202 * @param event
203 * The event on which to test the condition
204 * @return Whether the condition is true or not
205 * @throws AttributeNotFoundException
206 * The state attribute was not found
207 */
12685851 208 public boolean testForEvent(ITmfEvent event) throws AttributeNotFoundException {
1d7e62f9 209 ITmfStateSystem ss = fContainer.getStateSystem();
0f7276b6
GB
210 /*
211 * The condition is either the equality check of a state value or a
212 * boolean operation on other conditions
213 */
214 if (fStateValue != null) {
1d7e62f9
GB
215 ITmfXmlStateValue filter = fStateValue;
216 int quark = IXmlStateSystemContainer.ROOT_QUARK;
217 for (ITmfXmlStateAttribute attribute : filter.getAttributes()) {
0f7276b6
GB
218 quark = attribute.getAttributeQuark(event, quark);
219 /*
220 * When verifying a condition, the state attribute must exist,
221 * if it does not, the query is not valid, we stop the condition
222 * check
223 */
1d7e62f9 224 if (quark == IXmlStateSystemContainer.ERROR_QUARK) {
e13bd4cd 225 throw new AttributeNotFoundException(ss.getSSID() + " Attribute:" + attribute); //$NON-NLS-1$
0f7276b6
GB
226 }
227 }
228
229 /* Get the value to compare to from the XML file */
230 ITmfStateValue valueXML;
231 valueXML = filter.getValue(event);
232
233 /*
234 * The actual value: it can be either queried in the state system or
235 * found in the event
236 */
1d7e62f9
GB
237 ITmfStateValue valueState = (quark != IXmlStateSystemContainer.ROOT_QUARK) ? ss.queryOngoingState(quark) :
238 filter.getEventFieldValue(event);
12685851
GB
239 if (valueState == null) {
240 throw new IllegalStateException();
241 }
0f7276b6 242
5ddeee68 243 return compare(valueState, valueXML, fConditionOperator);
0f7276b6
GB
244
245 } else if (!fConditions.isEmpty()) {
246 /* Verify a condition tree */
247 switch (fOperator) {
248 case AND:
249 for (TmfXmlCondition childCondition : fConditions) {
250 if (!childCondition.testForEvent(event)) {
251 return false;
252 }
253 }
254 return true;
255 case NONE:
256 break;
257 case NOT:
258 return !fConditions.get(0).testForEvent(event);
259 case OR:
260 for (TmfXmlCondition childCondition : fConditions) {
261 if (childCondition.testForEvent(event)) {
262 return true;
263 }
264 }
265 return false;
266 default:
267 break;
268
269 }
270 } else {
271 throw new IllegalStateException("TmfXmlCondition: the condition should be either a state value or be the result of a condition tree"); //$NON-NLS-1$
272 }
273 return true;
274 }
275
446598f9
GB
276 @Override
277 public String toString() {
278 return "TmfXmlCondition: " + fOperator + " on " + fConditions; //$NON-NLS-1$ //$NON-NLS-2$
279 }
280
5ddeee68
NE
281 /**
282 * Compare two ITmfStateValues based on the given comparison operator
283 *
284 * @param source
285 * the state value to compare to
286 * @param dest
287 * the state value to be compared with
288 * @param comparisonOperator
289 * the operator to compare the inputs
290 * @return the boolean result of the comparison
291 */
292 public boolean compare(ITmfStateValue source, ITmfStateValue dest, ConditionOperator comparisonOperator) {
5ddeee68
NE
293 switch (comparisonOperator) {
294 case EQ:
295 return (source.compareTo(dest) == 0);
296 case NE:
297 return (source.compareTo(dest) != 0);
298 case GE:
299 return (source.compareTo(dest) >= 0);
300 case GT:
301 return (source.compareTo(dest) > 0);
302 case LE:
303 return (source.compareTo(dest) <= 0);
304 case LT:
305 return (source.compareTo(dest) < 0);
306 case NONE:
307 default:
308 throw new IllegalArgumentException("TmfXmlCondition: invalid comparison operator."); //$NON-NLS-1$
309 }
310
311 }
312
0f7276b6 313}
This page took 0.092642 seconds and 5 git commands to generate.