XML: Add multi-analyses views
authorGeneviève Bastien <gbastien+lttng@versatic.net>
Wed, 19 Apr 2017 21:13:52 +0000 (17:13 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Tue, 2 May 2017 14:38:38 +0000 (10:38 -0400)
This patch adds a new attribute to time graph view entry to be able to
use the state system from another analyses to populate some entries.

It also adds more regex support where path can contain place holders
like $1 to be replaced by any wildcard previously specified.

Change-Id: I13de7d2a4af091f4090ddc5ee61634739571c4d7
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/95379
Reviewed-by: Hudson CI
Reviewed-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
Tested-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/xmlView.xsd
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/META-INF/MANIFEST.MF
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/TmfXmlUiStrings.java
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlEntry.java
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java

index 1931843ea7a138f839a5f9b9dbd80d1fad44f353..ca7a73fab872cd70896bdec6c61c8afd55862b65 100644 (file)
                </xs:sequence>
                <xs:attribute name="path" type="xs:string" use="required" >
                        <xs:annotation>
-                               <xs:documentation>The path of the entry in the state system. Wildcards '*' may be used. For example, to display entries from all CPUs, the path could be "CPUs/*" and one entry will be created for each sub-attribute of the "CPUs" attribute. Each entry will be used as the base for all child elements, unless specified otherwise.</xs:documentation></xs:annotation></xs:attribute>
+                               <xs:documentation>The path of the entry in the state system. Wildcards '*' may be used. For example, to display entries from all CPUs, the path could be "CPUs/*" and one entry will be created for each sub-attribute of the "CPUs" attribute. Each entry will be used as the base for all child elements, unless specified otherwise. Child entries can use place holders for any previous wildcard, with '$1' being the first wildcard encountered.</xs:documentation></xs:annotation></xs:attribute>
+               <xs:attribute name="analysisId" type="xs:string" use="optional" >
+                       <xs:annotation>
+                               <xs:documentation>The ID of an analysis different from the one defined in the output and from which this entry will be taken. In this case, the corresponding path is always absolute and any entry underneath will refer to this analysis ID.</xs:documentation></xs:annotation></xs:attribute>
        </xs:complexType>
 
        <xs:complexType name="xyViewEntry">
index 76c3a1c976dfe770d5931d6a581a55da7ea1bf8d..b3a3b1fcb430a028e5adaf54794763ac05d0416a 100644 (file)
@@ -30,4 +30,5 @@ Export-Package: org.eclipse.tracecompass.internal.tmf.analysis.xml.ui;x-friends:
  org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.views.timegraph;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.ui.swtbot.tests",
  org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.views.xychart;x-internal:=true
 Import-Package: com.google.common.collect,
+ org.apache.commons.lang3,
  org.eclipse.ui.views.properties
index 30c804806698150aa5f063795a3420661cc85880..2b87851c36f2133687631b64858c8dd73d51f960 100644 (file)
@@ -32,6 +32,7 @@ public interface TmfXmlUiStrings {
 
     /* Elements and attributes of view entries */
     static final String PATH = "path";
+    static final String ANALYSIS_ID = "analysisId";
     static final String DISPLAY_ELEMENT = "display";
     static final String PARENT_ELEMENT = "parent";
     static final String NAME_ELEMENT = "name";
index d145f2569978778797dad3af8383ef897f1a71f2..b716bf671a9e782b7558d92957e266b042088a63 100644 (file)
@@ -18,7 +18,9 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.regex.Pattern;
 
+import org.apache.commons.lang3.StringUtils;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.ITmfXmlModelFactory;
 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.ITmfXmlStateAttribute;
 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlLocation;
@@ -39,7 +41,7 @@ import org.w3c.dom.Element;
  *
  * @author Florian Wininger
  */
-public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer {
+public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer, Comparable<XmlEntry> {
 
     private static final String EMPTY_STRING = ""; //$NON-NLS-1$
 
@@ -51,14 +53,14 @@ public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer
         DISPLAY
     }
 
-    private final ITmfTrace fTrace;
+    private final @NonNull ITmfTrace fTrace;
     private final EntryDisplayType fType;
     private final int fBaseQuark;
     private final int fDisplayQuark;
     private final String fParentId;
     private final String fId;
     private final @NonNull ITmfStateSystem fSs;
-    private final Element fElement;
+    private final @Nullable Element fElement;
 
     /**
      * Constructor
@@ -91,7 +93,7 @@ public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer
      *            used to determine, if available, the parent, ID, name and
      *            other display option of this entry
      */
-    public XmlEntry(int baseQuark, int displayQuark, ITmfTrace trace, String name, long startTime, long endTime, EntryDisplayType type, @NonNull ITmfStateSystem ss, Element entryElement) {
+    public XmlEntry(int baseQuark, int displayQuark, @NonNull ITmfTrace trace, String name, long startTime, long endTime, EntryDisplayType type, @NonNull ITmfStateSystem ss, Element entryElement) {
         super(name, startTime, endTime);
         fTrace = trace;
         fType = type;
@@ -139,7 +141,7 @@ public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer
      * @param ss
      *            The state system this entry belongs to
      */
-    public XmlEntry(int baseQuark, ITmfTrace trace, String name, @NonNull ITmfStateSystem ss) {
+    public XmlEntry(int baseQuark, @NonNull ITmfTrace trace, String name, @NonNull ITmfStateSystem ss) {
         super(name, ss.getStartTime(), ss.getCurrentEndTime());
         fTrace = trace;
         fType = EntryDisplayType.NULL;
@@ -174,7 +176,7 @@ public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer
      *
      * @return the entry's trace
      */
-    public ITmfTrace getTrace() {
+    public @NonNull ITmfTrace getTrace() {
         return fTrace;
     }
 
@@ -223,28 +225,6 @@ public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer
         return true;
     }
 
-    /**
-     * Add a child to this entry of type XmlEntry
-     *
-     * @param entry
-     *            The entry to add
-     */
-    public void addChild(@NonNull XmlEntry entry) {
-        int index;
-        for (index = 0; index < getChildren().size(); index++) {
-            XmlEntry other = (XmlEntry) getChildren().get(index);
-            if (entry.getType().compareTo(other.getType()) < 0) {
-                break;
-            } else if (entry.getType().equals(other.getType())) {
-                if (entry.getName().compareTo(other.getName()) < 0) {
-                    break;
-                }
-            }
-        }
-
-        addChild(index, entry);
-    }
-
     /**
      * Return the state system this entry is associated to
      *
@@ -282,4 +262,26 @@ public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer
         }
         return pattern.matcher(fParentId).find();
     }
+
+    @Override
+    public int compareTo(XmlEntry other) {
+        // First compare by type
+        int cmp = getType().compareTo(other.getType());
+        if (cmp != 0) {
+            return cmp;
+        }
+        // For equal type, then compare by element's attribute (to not mix
+        // different element's entries)
+        Element element = fElement;
+        String attrib = (element == null) ? StringUtils.EMPTY : element.getAttribute(TmfXmlUiStrings.PATH);
+        element = other.fElement;
+        String otherAttrib = (element == null) ? StringUtils.EMPTY : element.getAttribute(TmfXmlUiStrings.PATH);
+        cmp = attrib.compareTo(otherAttrib);
+        if (cmp != 0) {
+            return cmp;
+        }
+        // Then compare by name
+        return getName().compareTo(other.getName());
+    }
+
 }
index 953c9e1d544e90cb8d38ef3397bb069bed4c4701..ec700b93a11f48c6e6557cbe8dba3bd1525cdb3a 100644 (file)
@@ -221,4 +221,17 @@ public class XmlPresentationProvider extends TimeGraphPresentationProvider {
         return new RGB(r, g, b);
     }
 
+    /**
+     * Return whether an integer value has a corresponding index in the
+     * available states
+     *
+     * @param status
+     *            The numerical status of the event
+     * @return <code>true</code> if the numerical value is an existing value in
+     *         the available states
+     */
+    public boolean hasIndex(int status) {
+        return stateIndex.containsKey(status);
+    }
+
 }
index 219267aa2779920630c363f0090c5ce1377a7a89..71f16b9def99150a58f5c00336eca8fb8d90b420 100644 (file)
@@ -25,7 +25,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
+import org.apache.commons.lang3.StringUtils;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jdt.annotation.NonNull;
@@ -53,6 +56,7 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
 import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfXmlStrings;
 import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfXmlUtils;
 import org.eclipse.tracecompass.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
 import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
@@ -177,6 +181,16 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
         return Messages.XmlTimeGraphView_PreviousInterval;
     }
 
+    /**
+     * Getter for the presentation provider
+     *
+     * @return The time graph presentation provider
+     */
+    @Override
+    protected XmlPresentationProvider getPresentationProvider() {
+        return (XmlPresentationProvider) super.getPresentationProvider();
+    }
+
     /**
      * Default label provider, it shows name, id and parent columns
      *
@@ -210,13 +224,7 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
             if ((o1 instanceof XmlEntry) && (o2 instanceof XmlEntry)) {
                 XmlEntry entry1 = (XmlEntry) o1;
                 XmlEntry entry2 = (XmlEntry) o2;
-                result = entry1.getTrace().getStartTime().compareTo(entry2.getTrace().getStartTime());
-                if (result == 0) {
-                    result = entry1.getTrace().getName().compareTo(entry2.getTrace().getName());
-                }
-                if (result == 0) {
-                    result = entry1.getName().compareTo(entry2.getName());
-                }
+                result = entry1.compareTo(entry2);
             }
 
             if (result == 0) {
@@ -303,7 +311,7 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
 
                 /* Add children entry of this entry for each line */
                 for (Element entry : entries) {
-                    buildEntry(entry, groupEntry, -1);
+                    buildEntry(entry, groupEntry, -1, StringUtils.EMPTY);
                 }
             }
         }
@@ -323,7 +331,7 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
         }
     }
 
-    private void buildEntry(Element entryElement, XmlEntry parentEntry, int baseQuark) {
+    private void buildEntry(Element entryElement, XmlEntry parentEntry, int prevBaseQuark, String prevRegex) {
         /* Get the attribute string to display */
         String path = entryElement.getAttribute(TmfXmlUiStrings.PATH);
         if (path.isEmpty()) {
@@ -343,17 +351,37 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
             return;
         }
 
-        ITmfStateSystem ss = parentEntry.getStateSystem();
+        // Get the state system to use to populate those entries, by default, it is the same as the parent
+        String analysisId = entryElement.getAttribute(TmfXmlUiStrings.ANALYSIS_ID);
+        ITmfStateSystem parentSs = parentEntry.getStateSystem();
+        ITmfStateSystem ss = parentSs;
+        int baseQuark = prevBaseQuark;
+        if (!analysisId.isEmpty()) {
+            ss = TmfStateSystemAnalysisModule.getStateSystem(parentEntry.getTrace(), analysisId);
+            baseQuark = ITmfStateSystem.ROOT_ATTRIBUTE;
+            if (ss == null) {
+                return;
+            }
+        }
+
+        // Replace any place holders in the path
+        Pattern pattern = Pattern.compile(prevRegex);
+        String attributePath = prevBaseQuark > 0 ? parentSs.getFullAttributePath(prevBaseQuark) : StringUtils.EMPTY;
+        Matcher matcher = pattern.matcher(attributePath);
+        if (matcher.find()) {
+            path = matcher.replaceFirst(path);
+        }
+        String regexName = path.replaceAll("\\*", "(.*)");  //$NON-NLS-1$//$NON-NLS-2$
 
         /* Get the list of quarks to process with this path */
-        String[] paths = path.split(SPLIT_STRING);
+        String[] paths = regexName.split(SPLIT_STRING);
         int i = 0;
         List<Integer> quarks = Collections.singletonList(baseQuark);
 
         while (i < paths.length) {
             List<Integer> subQuarks = new LinkedList<>();
             /* Replace * by .* to have a regex string */
-            String name = paths[i].replaceAll("\\*", ".*"); //$NON-NLS-1$ //$NON-NLS-2$
+            String name = paths[i];
             for (int relativeQuark : quarks) {
                 for (int quark : ss.getSubAttributes(relativeQuark, false, name)) {
                     subQuarks.add(quark);
@@ -379,7 +407,7 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
             }
             /* Process the children entry of this entry */
             for (Element subEntryEl : entryElements) {
-                buildEntry(subEntryEl, currentEntry, quark);
+                buildEntry(subEntryEl, currentEntry, quark, prevRegex.isEmpty() ? regexName : prevRegex + '/' + regexName);
             }
         }
         if (!entryMap.isEmpty()) {
@@ -528,8 +556,23 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
         return eventList;
     }
 
+    private int getStringIndex(String stateStr) {
+        XmlPresentationProvider pres = getPresentationProvider();
+        Integer statusInt = fStringValueMap.get(stateStr);
+        if (statusInt != null) {
+            return statusInt;
+        }
+
+        // Add this new state to the presentation provider
+        int status = pres.addState(stateStr);
+        fStringValueMap.put(stateStr, status);
+        return status;
+
+    }
+
     private int getStatusFromInterval(ITmfStateInterval statusInterval) {
         ITmfStateValue stateValue = statusInterval.getStateValue();
+
         int status = -1;
         switch (stateValue.getType()) {
         case INTEGER:
@@ -538,20 +581,14 @@ public class XmlTimeGraphView extends AbstractTimeGraphView {
             break;
         case LONG:
             status = (int) stateValue.unboxLong();
+            XmlPresentationProvider pres = this.getPresentationProvider();
+            if (!pres.hasIndex(status)) {
+                status = getStringIndex("0x" + Long.toHexString(stateValue.unboxLong())); //$NON-NLS-1$
+            }
             break;
         case STRING:
             String statusStr = stateValue.unboxStr();
-            Integer statusInt = fStringValueMap.get(statusStr);
-            if (statusInt != null) {
-                status = statusInt;
-                break;
-            }
-            ITimeGraphPresentationProvider2 pres = this.getPresentationProvider();
-            if (pres instanceof XmlPresentationProvider) {
-                // Add this new state to the presentation provider
-                status = ((XmlPresentationProvider) pres).addState(statusStr);
-                fStringValueMap.put(statusStr, status);
-            }
+            status = getStringIndex(statusStr);
             break;
         case DOUBLE:
             status = (int) stateValue.unboxDouble();
This page took 0.031193 seconds and 5 git commands to generate.