From 1a23419e0c5697b2cd5995c606e9580600ca7fd0 Mon Sep 17 00:00:00 2001 From: Florian Wininger Date: Mon, 10 Mar 2014 15:42:47 -0400 Subject: [PATCH] TMF: Introduce the XML state system view for data driven outputs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: I3ecf738e918be7b52075706f85c3f842c737b712 Signed-off-by: Geneviève Bastien Signed-off-by: Florian Wininger Reviewed-on: https://git.eclipse.org/r/23161 Tested-by: Hudson CI Reviewed-by: Alexandre Montplaisir --- .../test_xml_files/test_valid.xml | 4 +- .../xml/core/module/xmlDefinition.xsd | 4 +- ...ateSystemView.xsd => xmlTimeGraphView.xsd} | 2 +- .../xml/core/stateprovider/TmfXmlStrings.java | 3 + .../META-INF/MANIFEST.MF | 3 +- .../plugin.properties | 2 + .../plugin.xml | 11 + .../tmf/analysis/xml/ui/TmfXmlUiStrings.java | 3 +- .../ui/module/TmfXmlAnalysisOutputSource.java | 30 +- .../xml/ui/module/TmfXmlViewOutput.java | 2 +- .../xml/ui/views/timegraph/Messages.java | 49 ++ .../xml/ui/views/timegraph/XmlEntry.java | 272 +++++++++ .../timegraph/XmlPresentationProvider.java | 220 +++++++ .../ui/views/timegraph/XmlTimeGraphView.java | 547 ++++++++++++++++++ .../ui/views/timegraph/messages.properties | 10 + 15 files changed, 1152 insertions(+), 10 deletions(-) rename org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/{xmlStateSystemView.xsd => xmlTimeGraphView.xsd} (98%) create mode 100644 org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/Messages.java create mode 100644 org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlEntry.java create mode 100644 org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java create mode 100644 org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java create mode 100644 org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/messages.properties diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.core.tests/test_xml_files/test_valid.xml b/org.eclipse.linuxtools.tmf.analysis.xml.core.tests/test_xml_files/test_valid.xml index 46911776a5..c463896276 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.core.tests/test_xml_files/test_valid.xml +++ b/org.eclipse.linuxtools.tmf.analysis.xml.core.tests/test_xml_files/test_valid.xml @@ -13,7 +13,7 @@ - + + diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlDefinition.xsd b/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlDefinition.xsd index 1783836f20..5c81260b22 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlDefinition.xsd +++ b/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlDefinition.xsd @@ -15,11 +15,11 @@ - + - + diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlStateSystemView.xsd b/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlTimeGraphView.xsd similarity index 98% rename from org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlStateSystemView.xsd rename to org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlTimeGraphView.xsd index 7064a9a48f..53f590356b 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlStateSystemView.xsd +++ b/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/module/xmlTimeGraphView.xsd @@ -13,7 +13,7 @@ - + diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/stateprovider/TmfXmlStrings.java b/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/stateprovider/TmfXmlStrings.java index b606c0a303..7e1fa5d505 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/stateprovider/TmfXmlStrings.java +++ b/org.eclipse.linuxtools.tmf.analysis.xml.core/src/org/eclipse/linuxtools/tmf/analysis/xml/core/stateprovider/TmfXmlStrings.java @@ -34,11 +34,14 @@ public interface TmfXmlStrings { static final String TRACETYPE = "traceType"; static final String ID = "id"; static final String LABEL = "label"; + static final String ANALYSIS = "analysis"; /* XML String */ static final String NULL = ""; static final String WILDCARD = "*"; static final String VARIABLE_PREFIX = "$"; + static final String COLOR = "color"; + static final String COLOR_PREFIX = "#"; /* XML Element Name */ static final String STATE_PROVIDER = "stateProvider"; diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.tmf.analysis.xml.ui/META-INF/MANIFEST.MF index 50c8ed6439..9de260d198 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/META-INF/MANIFEST.MF @@ -15,4 +15,5 @@ Require-Bundle: org.eclipse.ui, org.eclipse.linuxtools.tmf.analysis.xml.core Export-Package: org.eclipse.linuxtools.internal.tmf.analysis.xml.ui;x-friends:="org.eclipse.linuxtools.tmf.analysis.xml.ui.tests", org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.handler;x-internal:=true, - org.eclipse.linuxtools.tmf.analysis.xml.ui.module + org.eclipse.linuxtools.tmf.analysis.xml.ui.module, + org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.properties b/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.properties index ffa8775069..67a764c2a8 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.properties +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.properties @@ -17,3 +17,5 @@ Bundle-Name = Linux Tools TMF XML Analysis UI Plug-in command.xml.import = Import XML analysis command.xml.import.mnemonic = I command.xml.import.description = Import an XML file containing analysis information + +xmltimegraph.view.name = XML Time Graph View diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.xml b/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.xml index 30429ee514..a285ef34a1 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.xml +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/plugin.xml @@ -82,4 +82,15 @@ + + + + diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/internal/tmf/analysis/xml/ui/TmfXmlUiStrings.java b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/internal/tmf/analysis/xml/ui/TmfXmlUiStrings.java index fdab48320c..72af61dc61 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/internal/tmf/analysis/xml/ui/TmfXmlUiStrings.java +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/internal/tmf/analysis/xml/ui/TmfXmlUiStrings.java @@ -24,10 +24,9 @@ import org.eclipse.jdt.annotation.NonNullByDefault; public interface TmfXmlUiStrings { /* XML generic Element attribute names */ - static final String STATE_PROVIDER_VIEW = "stateSystemView"; + static final String TIME_GRAPH_VIEW = "timeGraphView"; /* View elements and attributes */ - static final String SSV_LINE = "line"; static final String ENTRY_ELEMENT = "entry"; /* Elements and attributes of view entries */ diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlAnalysisOutputSource.java b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlAnalysisOutputSource.java index 50bf81acbf..0960c824dc 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlAnalysisOutputSource.java +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlAnalysisOutputSource.java @@ -14,6 +14,7 @@ package org.eclipse.linuxtools.tmf.analysis.xml.ui.module; import java.io.File; import java.io.IOException; +import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -21,10 +22,17 @@ import javax.xml.parsers.ParserConfigurationException; import org.eclipse.core.runtime.IPath; import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.Activator; +import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.TmfXmlUiStrings; import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils; +import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; +import org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph.XmlTimeGraphView; import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisOutput; import org.eclipse.linuxtools.tmf.core.analysis.ITmfNewAnalysisModuleListener; +import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemAnalysisModule; import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** @@ -58,8 +66,28 @@ public class TmfXmlAnalysisOutputSource implements ITmfNewAnalysisModuleListener doc.getDocumentElement().normalize(); /* get state provider views if the analysis has state systems */ - /* TODO: Code here will come in later patch */ + if (module instanceof TmfStateSystemAnalysisModule) { + NodeList ssViewNodes = doc.getElementsByTagName(TmfXmlUiStrings.TIME_GRAPH_VIEW); + for (int i = 0; i < ssViewNodes.getLength(); i++) { + Element node = (Element) ssViewNodes.item(i); + /* Check if analysis is the right one */ + List headNodes = XmlUtils.getChildElements(node, TmfXmlStrings.HEAD); + if (headNodes.size() != 1) { + continue; + } + + List analysisNodes = XmlUtils.getChildElements(headNodes.get(0), TmfXmlStrings.ANALYSIS); + for (Element analysis : analysisNodes) { + String analysisId = analysis.getAttribute(TmfXmlStrings.ID); + if (analysisId.equals(module.getId())) { + IAnalysisOutput output = new TmfXmlViewOutput(XmlTimeGraphView.ID); + output.setOutputProperty(TmfXmlUiStrings.XML_OUTPUT_DATA, node.getAttribute(TmfXmlStrings.ID) + DATA_SEPARATOR + xmlFile.getAbsolutePath(), false); + module.registerOutput(output); + } + } + } + } } catch (ParserConfigurationException | SAXException | IOException e) { Activator.logError("Error opening XML file", e); //$NON-NLS-1$ } diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlViewOutput.java b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlViewOutput.java index 4ee6c64fc7..e6a4e95dc2 100644 --- a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlViewOutput.java +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/module/TmfXmlViewOutput.java @@ -64,7 +64,7 @@ public class TmfXmlViewOutput extends TmfAnalysisViewOutput { if ((viewId == null) || (filePath == null)) { return; } - Element viewElement = XmlUtils.getElementInFile(filePath, TmfXmlUiStrings.STATE_PROVIDER_VIEW, viewId); + Element viewElement = XmlUtils.getElementInFile(filePath, TmfXmlUiStrings.TIME_GRAPH_VIEW, viewId); if (viewElement == null) { return; } diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/Messages.java b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/Messages.java new file mode 100644 index 0000000000..700937ce15 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/Messages.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2014 École Polytechnique de Montréal + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Geneviève Bastien - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph; + +import org.eclipse.osgi.util.NLS; + +/** + * Message for the XML state system view + * + * @author Geneviève Bastien + */ +@SuppressWarnings("javadoc") +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph.messages"; //$NON-NLS-1$ + + public static String XmlPresentationProvider_MultipleStates; + + /* Default text messages */ + public static String XmlTimeGraphView_ColumnId; + public static String XmlTimeGraphView_ColumnName; + public static String XmlTimeGraphView_ColumnParentId; + public static String XmlTimeGraphView_DefaultTitle; + + /* Text and tooltips of the view */ + public static String XmlTimeGraphView_NextText; + public static String XmlTimeGraphView_NextTooltip; + public static String XmlTimeGraphView_PreviousInterval; + public static String XmlTimeGraphView_PreviousText; + + /* Errors and warnings messages */ + public static String XmlTimeGraphView_UselessEndPath; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlEntry.java b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlEntry.java new file mode 100644 index 0000000000..7ce77395d4 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlEntry.java @@ -0,0 +1,272 @@ +/******************************************************************************* + * Copyright (c) 2014 École Polytechnique de Montréal + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Florian Wininger - Initial API and implementation + * Geneviève Bastien - Review of the initial implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph; + +import java.util.Collections; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.TmfXmlUiStrings; +import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlModelFactory; +import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlStateAttribute; +import org.eclipse.linuxtools.tmf.analysis.xml.core.model.TmfXmlLocation; +import org.eclipse.linuxtools.tmf.analysis.xml.core.model.readonly.TmfXmlReadOnlyModelFactory; +import org.eclipse.linuxtools.tmf.analysis.xml.core.module.IXmlStateSystemContainer; +import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils; +import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; +import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException; +import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; +import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; +import org.w3c.dom.Element; + +/** + * An XML-defined entry, or row, to display in the XML state system view + * + * @author Florian Wininger + */ +public class XmlEntry extends TimeGraphEntry implements IXmlStateSystemContainer { + + private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + + /** Type of resource */ + public static enum EntryDisplayType { + /** Entries without events to display (filler rows, etc.) */ + NULL, + /** Entries with time events */ + DISPLAY + } + + private final 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; + + /** + * Constructor + * + * @param baseQuark + * The quark matching this entry, or -1 if no quark + * @param displayQuark + * The quark containing the value to display. It was needed by + * the caller to get the start and end time of this entry, so we + * receive it as parameter from him. + * @param trace + * The trace on which we are working (FIXME: is this parameter + * useful?) + * @param name + * The name of this entry. It will be overridden if a "name" XML + * tag is specified in the entryElement. It will also be used as + * the ID of this entry if no "id" XML tag is specified. It + * typically is the attribute name corresponding the the base + * quark. + * @param startTime + * The start time of this entry lifetime + * @param endTime + * The end time of this entry + * @param type + * The display type of this entry + * @param ss + * The state system this entry belongs to + * @param entryElement + * The XML element describing this entry. This element will be + * 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) { + super(name, startTime, endTime); + fTrace = trace; + fType = type; + fBaseQuark = baseQuark; + fDisplayQuark = displayQuark; + fSs = ss; + fElement = entryElement; + + /* Get the parent if specified */ + List elements = XmlUtils.getChildElements(fElement, TmfXmlUiStrings.PARENT_ELEMENT); + if (elements.size() > 0) { + fParentId = getFirstValue(elements.get(0)); + } else { + fParentId = EMPTY_STRING; + } + + /* Get the name of this entry */ + elements = XmlUtils.getChildElements(fElement, TmfXmlUiStrings.NAME_ELEMENT); + if (elements.size() > 0) { + String nameFromSs = getFirstValue(elements.get(0)); + if (!nameFromSs.isEmpty()) { + setName(nameFromSs); + } + } + + /* Get the id of this entry */ + elements = XmlUtils.getChildElements(fElement, TmfXmlUiStrings.ID_ELEMENT); + if (elements.size() > 0) { + fId = getFirstValue(elements.get(0)); + } else { + fId = name; + } + + } + + /** + * Constructor + * + * @param baseQuark + * The quark matching this entry, or -1 if no quark + * @param trace + * The trace on which we are working + * @param name + * The exec_name of this entry + * @param ss + * The state system this entry belongs to + */ + public XmlEntry(int baseQuark, ITmfTrace trace, String name, @NonNull ITmfStateSystem ss) { + super(name, ss.getStartTime(), ss.getCurrentEndTime()); + fTrace = trace; + fType = EntryDisplayType.NULL; + fBaseQuark = baseQuark; + fDisplayQuark = baseQuark; + fSs = ss; + fElement = null; + fParentId = EMPTY_STRING; + fId = name; + } + + /** Return the state value of the first interval with a non-null value */ + private String getFirstValue(Element stateAttribute) { + ITmfXmlModelFactory factory = TmfXmlReadOnlyModelFactory.getInstance(); + ITmfXmlStateAttribute display = factory.createStateAttribute(stateAttribute, this); + int quark = display.getAttributeQuark(fBaseQuark); + if (quark != IXmlStateSystemContainer.ERROR_QUARK) { + try { + /* Find the first attribute with a parent */ + List execNameIntervals = fSs.queryHistoryRange(quark, getStartTime(), getEndTime()); + for (ITmfStateInterval execNameInterval : execNameIntervals) { + + if (!execNameInterval.getStateValue().isNull()) { + return execNameInterval.getStateValue().toString(); + } + } + } catch (AttributeNotFoundException | StateSystemDisposedException e) { + } + } + return EMPTY_STRING; + } + + /** + * Get the trace this entry was taken from + * + * @return the entry's trace + */ + public ITmfTrace getTrace() { + return fTrace; + } + + /** + * Get the entry Type of this entry. Uses the inner EntryDisplayType enum. + * + * @return The entry type + */ + public EntryDisplayType getType() { + return fType; + } + + /** + * Get the quark from which to get the time event intervals for this entry. + * + * @return The attribute quark containing the intervals to display + */ + public int getDisplayQuark() { + return fDisplayQuark; + } + + /** + * Get this entry's ID + * + * @return The id of the entry. + */ + public String getId() { + return fId; + } + + /** + * Return the entry's parent ID. It corresponds to another entry's ID + * received from the {@link #getId()} method. + * + * @return The parent ID of this entry + */ + public String getParentId() { + return fParentId; + } + + @Override + public boolean hasTimeEvents() { + if (fType == EntryDisplayType.NULL) { + return false; + } + return true; + } + + /** + * Add a child to this entry of type XmlEntry + * + * @param entry + * The entry to add + */ + public void addChild(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; + } + } + } + + entry.setParent(this); + getChildren().add(index, entry); + } + + /** + * Return the state system this entry is associated to + * + * @return The state system, or null if the state system can't + * be found. + */ + @Override + @NonNull + public ITmfStateSystem getStateSystem() { + return fSs; + } + + @Override + public String getAttributeValue(String name) { + return name; + } + + @Override + public Iterable getLocations() { + return Collections.EMPTY_SET; + } + +} diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java new file mode 100644 index 0000000000..6d41049bf8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2014 École Polytechnique de Montréal + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Florian Wininger - Initial API and implementation + * Geneviève Bastien - Review of the initial implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.TmfXmlUiStrings; +import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils; +import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; +import org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph.XmlEntry.EntryDisplayType; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.StateItem; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; +import org.w3c.dom.Element; + +/** + * Presentation provider for the XML view, based on the generic TMF presentation + * provider. + * + * TODO: This should support colors/states defined for each entry element in the + * XML element. Also, event values may not be integers only (for instance, this + * wouldn't support yet the callstack view) + * + * @author Florian Wininger + */ +public class XmlPresentationProvider extends TimeGraphPresentationProvider { + + private List stateValues = new ArrayList<>(); + /* + * Maps the value of an event with the corresponding index in the + * stateValues list + */ + private Map stateIndex = new HashMap<>(); + + @Override + public int getStateTableIndex(ITimeEvent event) { + if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) { + TimeEvent tcEvent = (TimeEvent) event; + + XmlEntry entry = (XmlEntry) event.getEntry(); + int value = tcEvent.getValue(); + + if (entry.getType() == EntryDisplayType.DISPLAY) { + Integer index = stateIndex.get(value); + if (index == null) { + /* Colors won't be refreshed yet, return something known */ + index = TRANSPARENT; + stateIndex.put(value, stateValues.size()); + StateItem item = new StateItem(calcColor(stateValues.size()), String.valueOf(value)); + stateValues.add(item); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + fireColorSettingsChanged(); + } + }); + } + return index; + } + } + + return INVISIBLE; + } + + @Override + public StateItem[] getStateTable() { + return stateValues.toArray(new StateItem[stateValues.size()]); + } + + @Override + public String getEventName(ITimeEvent event) { + if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) { + TimeEvent tcEvent = (TimeEvent) event; + + XmlEntry entry = (XmlEntry) event.getEntry(); + int value = tcEvent.getValue(); + + if (entry.getType() == EntryDisplayType.DISPLAY) { + Integer index = stateIndex.get(value); + String rgb = stateValues.get(index).getStateString(); + return rgb; + } + return null; + } + return Messages.XmlPresentationProvider_MultipleStates; + } + + @Override + public Map getEventHoverToolTipInfo(ITimeEvent event, long hoverTime) { + /* + * TODO: Add the XML elements to support adding extra information in the + * tooltips and implement this + */ + return Collections.EMPTY_MAP; + } + + @Override + public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) { + /* + * TODO Add the XML elements to support texts in intervals and implement + * this + */ + } + + @Override + public void postDrawEntry(ITimeGraphEntry entry, Rectangle bounds, GC gc) { + } + + /** + * Loads the states from a {@link TmfXmlUiStrings#TIME_GRAPH_VIEW} XML + * element + * + * @param viewElement + * The XML view element + */ + public void loadNewStates(@NonNull Element viewElement) { + stateValues.clear(); + stateIndex.clear(); + List states = XmlUtils.getChildElements(viewElement, TmfXmlStrings.DEFINED_VALUE); + + for (Element state : states) { + int value = Integer.parseInt(state.getAttribute(TmfXmlStrings.VALUE)); + String name = state.getAttribute(TmfXmlStrings.NAME); + String color = state.getAttribute(TmfXmlStrings.COLOR); + + // FIXME Allow this case + if (value < 0) { + return; + } + + RGB colorRGB = new RGB(255, 0, 0); + if (color.startsWith(TmfXmlStrings.COLOR_PREFIX)) { + Integer hex = Integer.parseInt(color.substring(1), 16); + int hex1 = hex.intValue() % 256; + int hex2 = (hex.intValue() / 256) % 256; + int hex3 = (hex.intValue() / (256 * 256)) % 256; + colorRGB = new RGB(hex3, hex2, hex1); + } else { + colorRGB = calcColor(value); + } + + StateItem item = new StateItem(colorRGB, name); + + Integer index = stateIndex.get(value); + if (index == null) { + /* Add the new state value */ + stateIndex.put(value, stateValues.size()); + stateValues.add(item); + } else { + /* Override a previous state value */ + stateValues.set(index, item); + } + } + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + fireColorSettingsChanged(); + } + }); + } + + private static RGB calcColor(int value) { + int x = (value * 97) % 1530; + int r = 0, g = 0, b = 0; + if (x >= 0 && x < 255) { + r = 255; + g = x; + b = 0; + } + if (x >= 255 && x < 510) { + r = 510 - x; + g = 255; + b = 0; + } + if (x >= 510 && x < 765) { + r = 0; + g = 255; + b = x - 510; + } + if (x >= 765 && x < 1020) { + r = 0; + g = 1020 - x; + b = 255; + } + if (x >= 1020 && x < 1275) { + r = x - 1020; + g = 0; + b = 255; + } + if (x >= 1275 && x <= 1530) { + r = 255; + g = 0; + b = 1530 - x; + } + return new RGB(r, g, b); + } + +} diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java new file mode 100644 index 0000000000..2c00f58e96 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java @@ -0,0 +1,547 @@ +/******************************************************************************* + * Copyright (c) 2014 École Polytechnique de Montréal + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Florian Wininger - Initial API and implementation + * Geneviève Bastien - Review of the initial implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.Activator; +import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.TmfXmlUiStrings; +import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlModelFactory; +import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlStateAttribute; +import org.eclipse.linuxtools.tmf.analysis.xml.core.model.readonly.TmfXmlReadOnlyModelFactory; +import org.eclipse.linuxtools.tmf.analysis.xml.core.module.IXmlStateSystemContainer; +import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils; +import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; +import org.eclipse.linuxtools.tmf.analysis.xml.ui.module.TmfXmlAnalysisOutputSource; +import org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph.XmlEntry.EntryDisplayType; +import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; +import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException; +import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException; +import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException; +import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; +import org.eclipse.linuxtools.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems; +import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; +import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemAnalysisModule; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager; +import org.eclipse.linuxtools.tmf.ui.views.timegraph.AbstractTimeGraphView; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.NullTimeEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; +import org.eclipse.swt.widgets.Display; +import org.w3c.dom.Element; + +/** + * This view displays state system data in a time graph view. It uses an XML + * {@link TmfXmlUiStrings#TIME_GRAPH_VIEW} element from an XML file. This + * element defines which entries from the state system will be shown and also + * gives additional information on the presentation of the view (states, colors, + * etc) + * + * @author Florian Wininger + */ +public class XmlTimeGraphView extends AbstractTimeGraphView { + + /** View ID. */ + public static final String ID = "org.eclipse.linuxtools.tmf.analysis.xml.ui.views.timegraph"; //$NON-NLS-1$ + + private static final String XML_VIEW_ID_PROPERTY = "XmlViewId"; //$NON-NLS-1$ + private static final String XML_VIEW_FILE_PROPERTY = "XmlViewFile"; //$NON-NLS-1$ + + private static final String[] DEFAULT_COLUMN_NAMES = new String[] { + Messages.XmlTimeGraphView_ColumnName, + Messages.XmlTimeGraphView_ColumnId, + Messages.XmlTimeGraphView_ColumnParentId, + }; + + private static final String[] DEFAULT_FILTER_COLUMN_NAMES = new String[] { + Messages.XmlTimeGraphView_ColumnName, + Messages.XmlTimeGraphView_ColumnId + }; + + /** The relative weight of the sash */ + private static final int[] fWeight = { 1, 2 }; + + private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + private static final String SPLIT_STRING = "/"; //$NON-NLS-1$ + + private String fId = null; + private String fFilePath = null; + private final ITmfXmlModelFactory fFactory; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Default constructor + */ + public XmlTimeGraphView() { + super(ID, new XmlPresentationProvider()); + setWeight(fWeight); + setTreeColumns(DEFAULT_COLUMN_NAMES); + setTreeLabelProvider(new XmlTreeLabelProvider()); + setFilterColumns(DEFAULT_FILTER_COLUMN_NAMES); + setFilterLabelProvider(new XmlTreeLabelProvider()); + setEntryComparator(new XmlEntryComparator()); + this.addPartPropertyListener(new IPropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(TmfXmlUiStrings.XML_OUTPUT_DATA)) { + String data = (String) event.getNewValue(); + String[] idFile = data.split(TmfXmlAnalysisOutputSource.DATA_SEPARATOR); + fId = (idFile.length > 0) ? idFile[0] : null; + fFilePath = (idFile.length > 1) ? idFile[1] : null; + loadNewXmlView(); + savePersistentData(); + } + } + }); + IDialogSettings settings = getPersistentPropertyStore(); + + fId = settings.get(XML_VIEW_ID_PROPERTY); + fFilePath = settings.get(XML_VIEW_FILE_PROPERTY); + fFactory = TmfXmlReadOnlyModelFactory.getInstance(); + } + + @NonNull + private IDialogSettings getPersistentPropertyStore() { + IDialogSettings settings = Activator.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(getClass().getName()); + if (section == null) { + section = settings.addNewSection(getClass().getName()); + if (section == null) { + throw new IllegalStateException(); + } + } + return section; + } + + private void savePersistentData() { + IDialogSettings settings = getPersistentPropertyStore(); + + settings.put(XML_VIEW_ID_PROPERTY, fId); + settings.put(XML_VIEW_FILE_PROPERTY, fFilePath); + } + + private void loadNewXmlView() { + rebuild(); + } + + private void setViewTitle(final String title) { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + setPartName(title); + } + }); + + } + + @Override + protected String getNextText() { + return Messages.XmlTimeGraphView_NextText; + } + + @Override + protected String getNextTooltip() { + return Messages.XmlTimeGraphView_NextTooltip; + } + + @Override + protected String getPrevText() { + return Messages.XmlTimeGraphView_PreviousText; + } + + @Override + protected String getPrevTooltip() { + return Messages.XmlTimeGraphView_PreviousInterval; + } + + /** + * Default label provider, it shows name, id and parent columns + * + * TODO: There should be a way to define columns in the XML + * */ + private static class XmlTreeLabelProvider extends TreeLabelProvider { + + @Override + public String getColumnText(Object element, int columnIndex) { + XmlEntry entry = (XmlEntry) element; + + if (DEFAULT_COLUMN_NAMES[columnIndex].equals(Messages.XmlTimeGraphView_ColumnName)) { + return entry.getName(); + } else if (DEFAULT_COLUMN_NAMES[columnIndex].equals(Messages.XmlTimeGraphView_ColumnId)) { + return entry.getId(); + } else if (DEFAULT_COLUMN_NAMES[columnIndex].equals(Messages.XmlTimeGraphView_ColumnParentId)) { + return entry.getParentId(); + } + return EMPTY_STRING; + } + + } + + private static class XmlEntryComparator implements Comparator { + + @Override + public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) { + + int result = 0; + + 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()); + } + } + + if (result == 0) { + result = o1.getStartTime() < o2.getStartTime() ? -1 : o1.getStartTime() > o2.getStartTime() ? 1 : 0; + } + + return result; + } + } + + // ------------------------------------------------------------------------ + // Internal + // ------------------------------------------------------------------------ + + @Override + protected void buildEventList(ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor) { + + /* + * Get the view element from the XML file. If the element can't be + * found, return. + */ + String id = fId; + if (id == null) { + return; + } + Element viewElement = XmlUtils.getElementInFile(fFilePath, TmfXmlUiStrings.TIME_GRAPH_VIEW, id); + if (viewElement == null) { + return; + } + ITimeGraphPresentationProvider2 pres = this.getPresentationProvider(); + if (pres instanceof XmlPresentationProvider) { + /* + * TODO: Each entry of a line could have their own states/color. + * That will require an update to the presentation provider + */ + ((XmlPresentationProvider) pres).loadNewStates(viewElement); + } + + List heads = XmlUtils.getChildElements(viewElement, TmfXmlStrings.HEAD); + + List analysisIds = new LinkedList<>(); + if (!heads.isEmpty()) { + Element head = heads.get(0); + /* Set the title of this view from the label in the header */ + List labels = XmlUtils.getChildElements(head, TmfXmlStrings.LABEL); + String title = Messages.XmlTimeGraphView_DefaultTitle; + for (Element label : labels) { + if (!label.getAttribute(TmfXmlStrings.VALUE).equals(EMPTY_STRING)) { + title = label.getAttribute(TmfXmlStrings.VALUE); + } + break; + } + setViewTitle(title); + + /* Get the application analysis from the view's XML header */ + List applicableAnalysis = XmlUtils.getChildElements(head, TmfXmlStrings.ANALYSIS); + for (Element oneAnalysis : applicableAnalysis) { + analysisIds.add(oneAnalysis.getAttribute(TmfXmlStrings.ID)); + } + } + List entries = XmlUtils.getChildElements(viewElement, TmfXmlUiStrings.ENTRY_ELEMENT); + Set entryList = new TreeSet<>(getEntryComparator()); + for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) { + if (monitor.isCanceled()) { + return; + } + + List stateSystemModules = new LinkedList<>(); + if (analysisIds.isEmpty()) { + /* + * No analysis specified, take all state system analysis modules + */ + for (ITmfAnalysisModuleWithStateSystems module : aTrace.getAnalysisModulesOfClass(ITmfAnalysisModuleWithStateSystems.class)) { + stateSystemModules.add(module); + } + } else { + for (String moduleId : analysisIds) { + ITmfAnalysisModuleWithStateSystems module = aTrace.getAnalysisModuleOfClass(ITmfAnalysisModuleWithStateSystems.class, moduleId); + if (module != null) { + stateSystemModules.add(module); + } + } + } + + for (ITmfAnalysisModuleWithStateSystems module : stateSystemModules) { + module.schedule(); + if (module instanceof TmfStateSystemAnalysisModule) { + ((TmfStateSystemAnalysisModule) module).waitForInitialization(); + } + for (ITmfStateSystem ssq : module.getStateSystems()) { + if (ssq == null) { + return; + } + ssq.waitUntilBuilt(); + + long startTime = ssq.getStartTime(); + long endTime = ssq.getCurrentEndTime(); + XmlEntry groupEntry = new XmlEntry(-1, aTrace, aTrace.getName(), ssq); + entryList.add(groupEntry); + setStartTime(Math.min(getStartTime(), startTime)); + setEndTime(Math.max(getEndTime(), endTime)); + + /* Add children entry of this entry for each line */ + for (Element entry : entries) { + buildEntry(entry, groupEntry, -1); + } + } + } + } + putEntryList(trace, new ArrayList(entryList)); + + if (trace.equals(getTrace())) { + refresh(); + } + for (XmlEntry traceEntry : entryList) { + if (monitor.isCanceled()) { + return; + } + long startTime = traceEntry.getStateSystem().getStartTime(); + long endTime = traceEntry.getStateSystem().getCurrentEndTime() + 1; + buildStatusEvent(traceEntry, monitor, startTime, endTime); + } + } + + private void buildEntry(Element entryElement, XmlEntry parentEntry, int baseQuark) { + /* Get the attribute string to display */ + String path = entryElement.getAttribute(TmfXmlUiStrings.PATH); + if (path.isEmpty()) { + path = TmfXmlStrings.WILDCARD; + } + + /* + * Make sure the XML element has either a display attribute or entries, + * otherwise issue a warning + */ + + List displayElements = XmlUtils.getChildElements(entryElement, TmfXmlUiStrings.DISPLAY_ELEMENT); + List entryElements = XmlUtils.getChildElements(entryElement, TmfXmlUiStrings.ENTRY_ELEMENT); + + if (displayElements.isEmpty() && entryElements.isEmpty()) { + Activator.logWarning(String.format("XML view: entry for %s should have either a display element or entry elements", path)); //$NON-NLS-1$ + return; + } + + ITmfStateSystem ss = parentEntry.getStateSystem(); + + /* Get the list of quarks to process with this path */ + String[] paths = path.split(SPLIT_STRING); + int i = 0; + List quarks = Collections.singletonList(baseQuark); + + try { + while (i < paths.length) { + List subQuarks = new LinkedList<>(); + /* Replace * by .* to have a regex string */ + String name = paths[i].replaceAll("\\*", ".*"); //$NON-NLS-1$ //$NON-NLS-2$ + for (int relativeQuark : quarks) { + for (int quark : ss.getSubAttributes(relativeQuark, false, name)) { + subQuarks.add(quark); + } + } + quarks = subQuarks; + i++; + } + + /* Process each quark */ + XmlEntry currentEntry = parentEntry; + Element displayElement = null; + Map entryMap = new HashMap<>(); + if (!displayElements.isEmpty()) { + displayElement = displayElements.get(0); + } + for (int quark : quarks) { + currentEntry = parentEntry; + /* Process the current entry, if specified */ + if (displayElement != null) { + currentEntry = processEntry(entryElement, displayElement, parentEntry, quark, ss); + entryMap.put(currentEntry.getId(), currentEntry); + } + /* Process the children entry of this entry */ + for (Element subEntryEl : entryElements) { + buildEntry(subEntryEl, currentEntry, quark); + } + } + if (!entryMap.isEmpty()) { + buildTree(entryMap, parentEntry); + } + } catch (AttributeNotFoundException e) { + } + } + + private XmlEntry processEntry(@NonNull Element entryElement, @NonNull Element displayEl, + XmlEntry parentEntry, int quark, ITmfStateSystem ss) { + /* + * Get the start time and end time of this entry from the display + * attribute + */ + ITmfXmlStateAttribute display = fFactory.createStateAttribute(displayEl, parentEntry); + int displayQuark = display.getAttributeQuark(quark); + if (displayQuark == IXmlStateSystemContainer.ERROR_QUARK) { + return new XmlEntry(quark, parentEntry.getTrace(), + String.format("Unknown display quark for %s", ss.getAttributeName(quark)), ss); //$NON-NLS-1$ + } + + long entryStart = ss.getStartTime(); + long entryEnd = ss.getCurrentEndTime(); + try { + boolean first = true; + List execNameIntervals = ss.queryHistoryRange(displayQuark, ss.getStartTime(), ss.getCurrentEndTime()); + + for (ITmfStateInterval execNameInterval : execNameIntervals) { + + if (!execNameInterval.getStateValue().isNull()) { + if (first) { + entryStart = execNameInterval.getStartTime(); + first = false; + } + entryEnd = execNameInterval.getEndTime(); + } + } + } catch (AttributeNotFoundException | StateSystemDisposedException e) { + } + + return new XmlEntry(quark, displayQuark, parentEntry.getTrace(), ss.getAttributeName(quark), + entryStart, entryEnd, EntryDisplayType.DISPLAY, ss, entryElement); + } + + private void buildStatusEvent(XmlEntry traceEntry, IProgressMonitor monitor, long start, long end) { + long resolution = (end - start) / getDisplayWidth(); + long startTime = Math.max(start, traceEntry.getStartTime()); + long endTime = Math.min(end + 1, traceEntry.getEndTime()); + List eventList = getEventList(traceEntry, startTime, endTime, resolution, monitor); + if (monitor.isCanceled()) { + return; + } + traceEntry.setEventList(eventList); + redraw(); + + for (TimeGraphEntry entry : traceEntry.getChildren()) { + if (monitor.isCanceled()) { + return; + } + XmlEntry xmlEntry = (XmlEntry) entry; + buildStatusEvent(xmlEntry, monitor, start, end); + } + } + + /** Build a tree using getParentId() and getId() */ + private static void buildTree(Map entryMap, XmlEntry rootEntry) { + for (XmlEntry entry : entryMap.values()) { + boolean root = true; + if (!entry.getParentId().isEmpty()) { + XmlEntry parent = entryMap.get(entry.getParentId()); + if (parent != null && + entry.getStartTime() >= parent.getStartTime() && + entry.getStartTime() <= parent.getEndTime()) { + parent.addChild(entry); + root = false; + } + } + if (root) { + rootEntry.addChild(entry); + } + } + } + + @Override + protected List getEventList(TimeGraphEntry entry, long startTime, long endTime, long resolution, IProgressMonitor monitor) { + if (!(entry instanceof XmlEntry)) { + return Collections.EMPTY_LIST; + } + XmlEntry xmlEntry = (XmlEntry) entry; + ITmfStateSystem ssq = xmlEntry.getStateSystem(); + final long realStart = Math.max(startTime, entry.getStartTime()); + final long realEnd = Math.min(endTime, entry.getEndTime()); + if (realEnd <= realStart) { + return null; + } + List eventList = null; + int quark = xmlEntry.getDisplayQuark(); + + try { + if (xmlEntry.getType() == EntryDisplayType.DISPLAY) { + + List statusIntervals = ssq.queryHistoryRange(quark, realStart, realEnd - 1, resolution, monitor); + eventList = new ArrayList<>(statusIntervals.size()); + long lastEndTime = -1; + for (ITmfStateInterval statusInterval : statusIntervals) { + if (monitor.isCanceled()) { + return null; + } + int status = statusInterval.getStateValue().unboxInt(); + long time = statusInterval.getStartTime(); + long duration = statusInterval.getEndTime() - time + 1; + if (!statusInterval.getStateValue().isNull()) { + if (lastEndTime != time && lastEndTime != -1) { + eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime)); + } + eventList.add(new TimeEvent(entry, time, duration, status)); + } else if (lastEndTime == -1 || time + duration >= endTime) { + // add null event if it intersects the start or end time + eventList.add(new NullTimeEvent(entry, time, duration)); + } + lastEndTime = time + duration; + } + } + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException | StateSystemDisposedException e) { + /* Ignored */ + } + return eventList; + } + + @Override + protected List getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) { + /* TODO: not implemented yet, need XML to go along */ + return Collections.EMPTY_LIST; + } + +} diff --git a/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/messages.properties b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/messages.properties new file mode 100644 index 0000000000..73b9566d2d --- /dev/null +++ b/org.eclipse.linuxtools.tmf.analysis.xml.ui/src/org/eclipse/linuxtools/tmf/analysis/xml/ui/views/timegraph/messages.properties @@ -0,0 +1,10 @@ +XmlPresentationProvider_MultipleStates=(multiple) +XmlTimeGraphView_ColumnId=ID +XmlTimeGraphView_ColumnName=Name +XmlTimeGraphView_ColumnParentId=ParentID +XmlTimeGraphView_DefaultTitle=Xml State Provider +XmlTimeGraphView_NextText=Next Interval +XmlTimeGraphView_NextTooltip=Select next interval in time graph +XmlTimeGraphView_PreviousInterval=Select previous interval in time graph +XmlTimeGraphView_PreviousText=Previous Interval +XmlTimeGraphView_UselessEndPath=There should be an XML for path {0} in the view's XML otherwise the last level is useless -- 2.34.1