tmf : Add comparison between two state values in the XML core
authorJean-Christian Kouame <jean-christian.kouame@ericsson.com>
Mon, 30 Nov 2015 17:56:48 +0000 (12:56 -0500)
committerBernd Hufmann <bernd.hufmann@ericsson.com>
Tue, 8 Dec 2015 19:50:32 +0000 (14:50 -0500)
Previously, it was only possible to compare a state value to a constant.
Now, we can compare directly two state values. With that, it is possible
to query and compare two state values already stored in the state
system. For now, only the "equal" operator is supported.

Change-Id: Iebbcb90c2c0603c5ec1191530e25dd3b0a1cf853
Signed-off-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/61671
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Hudson CI
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/model/TmfXmlCondition.java
tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/xmlStateProvider.xsd

index a5f286c0f5ba2e2d4d14c88fbbd0b169e5e913b1..8b97c6c7f50559af3dd915c43375d1813f49e50d 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2015 Ecole Polytechnique de Montreal
+ * Copyright (c) 2014, 2015 Ecole Polytechnique de Montreal and others
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
@@ -10,6 +10,7 @@
  *   Florian Wininger - Initial API and implementation
  *   Naser Ezzati - Add the comparison operators
  *   Patrick Tasse - Add message to exceptions
+ *   Jean-Christian Kouame - Add comparison between two state values
  ******************************************************************************/
 
 package org.eclipse.tracecompass.tmf.analysis.xml.core.model;
@@ -18,6 +19,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
@@ -39,6 +41,8 @@ import org.w3c.dom.Element;
  *       <stateValue type="null" />
  *   </condition>
  *   <condition>
+ *      <stateValue type="long" value="2" />
+ *      <stateValue type="long" value="5" />
  *   </condition>
  * </and>
  * </pre>
@@ -48,7 +52,7 @@ import org.w3c.dom.Element;
 public class TmfXmlCondition {
 
     private final List<TmfXmlCondition> fConditions = new ArrayList<>();
-    private final @Nullable ITmfXmlStateValue fStateValue;
+    private final List<ITmfXmlStateValue> fStateValues;
     private final LogicalOperator fOperator;
     private final IXmlStateSystemContainer fContainer;
     private final ConditionOperator fConditionOperator;
@@ -86,6 +90,7 @@ public class TmfXmlCondition {
         Element rootNode = node;
         /* Process the conditions: in each case, only process Element nodes */
         List<@Nullable Element> childElements = XmlUtils.getChildElements(rootNode);
+        final Element firstElement = NonNullUtils.checkNotNull(childElements.get(0));
 
         /*
          * If the node is an if, take the child as the root condition
@@ -94,90 +99,37 @@ public class TmfXmlCondition {
          */
         if (node.getNodeName().equals(TmfXmlStrings.IF)) {
             if (childElements.isEmpty()) {
-                throw new IllegalArgumentException("TmfXmlCondition constructor: IF node has no child element"); //$NON-NLS-1$
+                throw new IllegalArgumentException("TmfXmlCondition constructor: IF node with no child element"); //$NON-NLS-1$
             }
-            rootNode = childElements.get(0);
+            rootNode = firstElement;
             childElements = XmlUtils.getChildElements(rootNode);
         }
-
-        if (rootNode == null) {
-            throw new IllegalArgumentException();
+        int size = rootNode.getElementsByTagName(TmfXmlStrings.STATE_VALUE).getLength();
+        fStateValues = new ArrayList<>(size);
+        if (size > 2 || size == 0) {
+            throw new IllegalArgumentException("TmfXmlCondition: a condition should have 1 or 2 state values at most"); //$NON-NLS-1$
         }
 
         switch (rootNode.getNodeName()) {
         case TmfXmlStrings.CONDITION:
             fOperator = LogicalOperator.NONE;
-            /* Read comparison type */
-            String equationType = rootNode.getAttribute(TmfXmlStrings.OPERATOR);
-
-            switch (equationType) {
-            case TmfXmlStrings.EQ:
-                fConditionOperator = ConditionOperator.EQ;
-                break;
-            case TmfXmlStrings.NE:
-                fConditionOperator = ConditionOperator.NE;
-                break;
-            case TmfXmlStrings.GE:
-                fConditionOperator = ConditionOperator.GE;
-                break;
-            case TmfXmlStrings.GT:
-                fConditionOperator = ConditionOperator.GT;
-                break;
-            case TmfXmlStrings.LE:
-                fConditionOperator = ConditionOperator.LE;
-                break;
-            case TmfXmlStrings.LT:
-                fConditionOperator = ConditionOperator.LT;
-                break;
-            case TmfXmlStrings.NULL:
-                fConditionOperator = ConditionOperator.EQ;
-                break;
-            default:
-                throw new IllegalArgumentException("TmfXmlCondition: invalid comparison operator."); //$NON-NLS-1$
-            }
-            /* The last element is a state value node */
-            Element stateValueElement = childElements.remove(childElements.size() - 1);
-            if (stateValueElement == null) {
-                throw new IllegalStateException();
-            }
-
-            /*
-             * A state value is either preceded by an eventField or a number of
-             * state attributes
-             */
-            @Nullable Element firstChild = childElements.get(0);
-            if (firstChild == null) {
-                throw new IllegalStateException();
-            }
-
-            if (childElements.size() == 1 && firstChild.getNodeName().equals(TmfXmlStrings.ELEMENT_FIELD)) {
-                String attribute = firstChild.getAttribute(TmfXmlStrings.NAME);
-                fStateValue = modelFactory.createStateValue(stateValueElement, fContainer, attribute);
+            if (size == 1) {
+                fConditionOperator = getConditionOperator(rootNode);
+                getStateValuesForXmlCondition(modelFactory, NonNullUtils.checkNotNull(childElements));
             } else {
-                List<ITmfXmlStateAttribute> attributes = new ArrayList<>();
-                for (Element element : childElements) {
-                    if (element == null || !element.getNodeName().equals(TmfXmlStrings.STATE_ATTRIBUTE)) {
-                        throw new IllegalArgumentException("TmfXmlCondition: a condition either has a eventField element or a number of TmfXmlStateAttribute elements before the state value"); //$NON-NLS-1$
-                    }
-                    ITmfXmlStateAttribute attribute = modelFactory.createStateAttribute(element, fContainer);
-                    attributes.add(attribute);
-                }
-                fStateValue = modelFactory.createStateValue(stateValueElement, fContainer, attributes);
+                fConditionOperator = ConditionOperator.EQ;
+                fStateValues.add(modelFactory.createStateValue(NonNullUtils.checkNotNull(childElements.get(0)), fContainer, new ArrayList<ITmfXmlStateAttribute>()));
+                fStateValues.add(modelFactory.createStateValue(NonNullUtils.checkNotNull(childElements.get(1)), fContainer, new ArrayList<ITmfXmlStateAttribute>()));
             }
             break;
         case TmfXmlStrings.NOT:
             fOperator = LogicalOperator.NOT;
-            fStateValue = null;
             fConditionOperator = ConditionOperator.NONE;
-            Element element = childElements.get(0);
-            if (element == null) {
-                throw new IllegalArgumentException();
-            }
+            Element element = firstElement;
             fConditions.add(modelFactory.createCondition(element, fContainer));
             break;
         case TmfXmlStrings.AND:
             fOperator = LogicalOperator.AND;
-            fStateValue = null;
             fConditionOperator = ConditionOperator.NONE;
             for (Element condition : childElements) {
                 if (condition == null) {
@@ -188,7 +140,6 @@ public class TmfXmlCondition {
             break;
         case TmfXmlStrings.OR:
             fOperator = LogicalOperator.OR;
-            fStateValue = null;
             fConditionOperator = ConditionOperator.NONE;
             for (Element condition : childElements) {
                 if (condition == null) {
@@ -202,6 +153,54 @@ public class TmfXmlCondition {
         }
     }
 
+    private void getStateValuesForXmlCondition(ITmfXmlModelFactory modelFactory, List<@Nullable Element> childElements) {
+        Element stateValueElement = NonNullUtils.checkNotNull(childElements.remove(childElements.size() - 1));
+        /*
+         * A state value is either preceded by an eventField or a number of
+         * state attributes
+         */
+        final Element firstElement = NonNullUtils.checkNotNull(childElements.get(0));
+        if (childElements.size() == 1 && firstElement.getNodeName().equals(TmfXmlStrings.ELEMENT_FIELD)) {
+            String attribute = firstElement.getAttribute(TmfXmlStrings.NAME);
+            fStateValues.add(modelFactory.createStateValue(stateValueElement, fContainer, attribute));
+        } else {
+            List<ITmfXmlStateAttribute> attributes = new ArrayList<>();
+            for (Element element : childElements) {
+                if (element == null) {
+                    throw new NullPointerException("There should be at list one element"); //$NON-NLS-1$
+                }
+                if (!element.getNodeName().equals(TmfXmlStrings.STATE_ATTRIBUTE)) {
+                    throw new IllegalArgumentException("TmfXmlCondition: a condition either has a eventField element or a number of TmfXmlStateAttribute elements before the state value"); //$NON-NLS-1$
+                }
+                ITmfXmlStateAttribute attribute = modelFactory.createStateAttribute(element, fContainer);
+                attributes.add(attribute);
+            }
+            fStateValues.add(modelFactory.createStateValue(stateValueElement, fContainer, attributes));
+        }
+    }
+
+    private static ConditionOperator getConditionOperator(Element rootNode) {
+        String equationType = rootNode.getAttribute(TmfXmlStrings.OPERATOR);
+        switch (equationType) {
+        case TmfXmlStrings.EQ:
+            return ConditionOperator.EQ;
+        case TmfXmlStrings.NE:
+            return ConditionOperator.NE;
+        case TmfXmlStrings.GE:
+            return ConditionOperator.GE;
+        case TmfXmlStrings.GT:
+            return ConditionOperator.GT;
+        case TmfXmlStrings.LE:
+            return ConditionOperator.LE;
+        case TmfXmlStrings.LT:
+            return ConditionOperator.LT;
+        case TmfXmlStrings.NULL:
+            return ConditionOperator.EQ;
+        default:
+            throw new IllegalArgumentException("TmfXmlCondition: invalid comparison operator."); //$NON-NLS-1$
+        }
+    }
+
     /**
      * Test the result of the condition for an event
      *
@@ -210,44 +209,12 @@ public class TmfXmlCondition {
      * @return Whether the condition is true or not
      * @throws AttributeNotFoundException
      *             The state attribute was not found
+     * @since 1.0
      */
     public boolean testForEvent(ITmfEvent event) throws AttributeNotFoundException {
         ITmfStateSystem ss = fContainer.getStateSystem();
-        /*
-         * The condition is either the equality check of a state value or a
-         * boolean operation on other conditions
-         */
-        if (fStateValue != null) {
-            ITmfXmlStateValue filter = fStateValue;
-            int quark = IXmlStateSystemContainer.ROOT_QUARK;
-            for (ITmfXmlStateAttribute attribute : filter.getAttributes()) {
-                quark = attribute.getAttributeQuark(event, quark);
-                /*
-                 * When verifying a condition, the state attribute must exist,
-                 * if it does not, the query is not valid, we stop the condition
-                 * check
-                 */
-                if (quark == IXmlStateSystemContainer.ERROR_QUARK) {
-                    throw new AttributeNotFoundException(ss.getSSID() + " Attribute:" + attribute); //$NON-NLS-1$
-                }
-            }
-
-            /* Get the value to compare to from the XML file */
-            ITmfStateValue valueXML;
-            valueXML = filter.getValue(event);
-
-            /*
-             * The actual value: it can be either queried in the state system or
-             * found in the event
-             */
-            ITmfStateValue valueState = (quark != IXmlStateSystemContainer.ROOT_QUARK) ? ss.queryOngoingState(quark) :
-                    filter.getEventFieldValue(event);
-            if (valueState == null) {
-                throw new IllegalStateException();
-            }
-
-            return compare(valueState, valueXML, fConditionOperator);
-
+        if (!fStateValues.isEmpty()) {
+            return testForEvent(event, NonNullUtils.checkNotNull(ss));
         } else if (!fConditions.isEmpty()) {
             /* Verify a condition tree */
             switch (fOperator) {
@@ -273,12 +240,50 @@ public class TmfXmlCondition {
                 break;
 
             }
-        } else {
-            throw new IllegalStateException("TmfXmlCondition: the condition should be either a state value or be the result of a condition tree"); //$NON-NLS-1$
         }
         return true;
     }
 
+    private boolean testForEvent(ITmfEvent event, ITmfStateSystem ss) throws AttributeNotFoundException {
+        /*
+         * The condition is either the equality check of a state value or a
+         * boolean operation on other conditions
+         */
+        if (fStateValues.size() == 1) {
+            ITmfXmlStateValue filter = fStateValues.get(0);
+            int quark = IXmlStateSystemContainer.ROOT_QUARK;
+            for (ITmfXmlStateAttribute attribute : filter.getAttributes()) {
+                quark = attribute.getAttributeQuark(event, quark);
+                /*
+                 * When verifying a condition, the state attribute must exist,
+                 * if it does not, the query is not valid, we stop the condition
+                 * check
+                 */
+                if (quark == IXmlStateSystemContainer.ERROR_QUARK) {
+                    throw new AttributeNotFoundException(ss.getSSID() + " Attribute:" + attribute); //$NON-NLS-1$
+                }
+            }
+
+            /*
+             * The actual value: it can be either queried in the state system or
+             * found in the event
+             */
+            ITmfStateValue valueState = (quark != IXmlStateSystemContainer.ROOT_QUARK) ? ss.queryOngoingState(quark) : filter.getEventFieldValue(event);
+            if (valueState == null) {
+                throw new IllegalStateException("TmfXmlCondition : The state value does not exist in the state system"); //$NON-NLS-1$
+            }
+
+            /* Get the value to compare to from the XML file */
+            ITmfStateValue valueXML;
+            valueXML = filter.getValue(event);
+            return compare(valueState, valueXML, fConditionOperator);
+        }
+        /* Get the two values needed for the comparison */
+        ITmfStateValue valuesXML1 = fStateValues.get(0).getValue(event);
+        ITmfStateValue valuesXML2 = fStateValues.get(1).getValue(event);
+        return valuesXML1.equals(valuesXML2);
+    }
+
     @Override
     public String toString() {
         return "TmfXmlCondition: " + fOperator + " on " + fConditions; //$NON-NLS-1$ //$NON-NLS-2$
@@ -297,6 +302,7 @@ public class TmfXmlCondition {
      */
     public boolean compare(ITmfStateValue source, ITmfStateValue dest, ConditionOperator comparisonOperator) {
         switch (comparisonOperator) {
+        //TODO The comparison operator should have a compareHelper that calls compare
         case EQ:
             return (source.compareTo(dest) == 0);
         case NE:
@@ -313,7 +319,5 @@ public class TmfXmlCondition {
         default:
             throw new IllegalArgumentException("TmfXmlCondition: invalid comparison operator."); //$NON-NLS-1$
         }
-
     }
-
 }
\ No newline at end of file
index f7178df3440e3b77dff143ea11c7a2a312201d47..d957ee9af046498e04ec52d7df5ac4374fceac89 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!-- ***************************************************************************
- * Copyright (c) 2014 École Polytechnique de Montréal
+ * Copyright (c) 2014 École Polytechnique de Montréal and others
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
        <xs:complexType name="condition">
                <xs:annotation>
                        <xs:documentation>Define a conditional statement. Conditions may use values of the state system or from the event being handled. This element defines a statement in the form of "if (some_path == value)".</xs:documentation></xs:annotation>
-               <xs:sequence maxOccurs="1" minOccurs="1">
-                       <xs:choice maxOccurs="1" minOccurs="1">
-                               <xs:element maxOccurs="unbounded" minOccurs="1" name="stateAttribute" type="stateAttribute" >
-                                       <xs:annotation>
-                                               <xs:documentation>Compare the current value of an attribute of the state system.</xs:documentation></xs:annotation></xs:element>
-                               <xs:element maxOccurs="1" minOccurs="1" name="field" type="eventField" >
+               <xs:choice>
+                       <xs:sequence>
+                               <xs:choice maxOccurs="1" minOccurs="1">
+                                       <xs:element maxOccurs="unbounded" minOccurs="1" name="stateAttribute" type="stateAttribute" >
+                                               <xs:annotation>
+                                                       <xs:documentation>Compare the current value of an attribute of the state system.</xs:documentation></xs:annotation></xs:element>
+                                       <xs:element maxOccurs="1" minOccurs="1" name="field" type="eventField" >
+                                               <xs:annotation>
+                                                       <xs:documentation>Compare the value of an event field.</xs:documentation></xs:annotation></xs:element>
+                               </xs:choice>
+                               <xs:element maxOccurs="1" minOccurs="1" name="stateValue" type="stateValue" >
                                        <xs:annotation>
-                                               <xs:documentation>Compare the value of an event field.</xs:documentation></xs:annotation></xs:element>
-                       </xs:choice>
-                       <xs:element maxOccurs="1" minOccurs="1" name="stateValue" type="stateValue" >
-                               <xs:annotation>
-                                       <xs:documentation>Define the value to compare to.</xs:documentation></xs:annotation></xs:element>
-               </xs:sequence>
+                                               <xs:documentation>Define the value to compare to.</xs:documentation></xs:annotation></xs:element>
+                       </xs:sequence>
+                       <xs:sequence>
+                               <xs:element maxOccurs="2" minOccurs="2" name="stateValue" type="stateValue"/>
+                       </xs:sequence>
+               </xs:choice>
 
                <xs:attribute name="operator" default="eq">
                        <xs:annotation>
This page took 0.030352 seconds and 5 git commands to generate.