tmf: Fix Call Stack view empty for experiments
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.analysis.xml.ui / src / org / eclipse / linuxtools / internal / tmf / analysis / xml / ui / views / xychart / XmlXYViewer.java
CommitLineData
87c5447c
GB
1/*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.views.xychart;
14
15import java.util.Collections;
16import java.util.HashMap;
17import java.util.LinkedList;
18import java.util.List;
19import java.util.Map;
20import java.util.regex.Pattern;
21
22import org.eclipse.core.runtime.IProgressMonitor;
23import org.eclipse.jdt.annotation.NonNull;
24import org.eclipse.jdt.annotation.Nullable;
25import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.Activator;
26import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.TmfXmlUiStrings;
27import org.eclipse.linuxtools.internal.tmf.analysis.xml.ui.views.XmlViewInfo;
28import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
29import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
30import org.eclipse.linuxtools.statesystem.core.exceptions.StateSystemDisposedException;
31import org.eclipse.linuxtools.statesystem.core.exceptions.StateValueTypeException;
32import org.eclipse.linuxtools.statesystem.core.exceptions.TimeRangeException;
33import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue;
34import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlModelFactory;
35import org.eclipse.linuxtools.tmf.analysis.xml.core.model.ITmfXmlStateAttribute;
36import org.eclipse.linuxtools.tmf.analysis.xml.core.model.TmfXmlLocation;
37import org.eclipse.linuxtools.tmf.analysis.xml.core.model.readonly.TmfXmlReadOnlyModelFactory;
38import org.eclipse.linuxtools.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
39import org.eclipse.linuxtools.tmf.analysis.xml.core.module.XmlUtils;
40import org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
41import org.eclipse.linuxtools.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems;
42import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemAnalysisModule;
43import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
aa9b2552 44import org.eclipse.linuxtools.tmf.ui.TmfUiRefreshHandler;
87c5447c
GB
45import org.eclipse.linuxtools.tmf.ui.viewers.xycharts.linecharts.TmfCommonXLineChartViewer;
46import org.eclipse.swt.widgets.Composite;
47import org.w3c.dom.Element;
48
49/**
50 * Main viewer to display XML-defined xy charts. It uses an XML
51 * {@link TmfXmlUiStrings#XY_VIEW} element from an XML file. This element
52 * defines which entries from the state system will be shown and also gives
53 * additional information on the presentation of the view.
54 *
55 * @author Geneviève Bastien
56 */
57public class XmlXYViewer extends TmfCommonXLineChartViewer {
58
59 private static final String SPLIT_STRING = "/"; //$NON-NLS-1$
87c5447c
GB
60
61 @SuppressWarnings("null")
62 private static final @NonNull Pattern WILDCARD_PATTERN = Pattern.compile("\\*"); //$NON-NLS-1$
63
64 private final ITmfXmlModelFactory fFactory = TmfXmlReadOnlyModelFactory.getInstance();
65 private final Map<Integer, SeriesData> fSeriesData = new HashMap<>();
66
67 private final XmlViewInfo fViewInfo;
68
69 /** XML Model elements to use to create the series */
70 private @Nullable ITmfXmlStateAttribute fDisplay;
71 private @Nullable ITmfXmlStateAttribute fSeriesName;
72 private @Nullable XmlXYEntry fEntry;
73
74 /**
75 * The information related to one series on the chart
76 */
77 private class SeriesData {
78
79 private final double[] fYValues;
80 private final Integer fDisplayQuark;
81 private final String fName;
82
83 public SeriesData(int length, int attributeQuark, String seriesName) {
84 fYValues = new double[length];
85 fDisplayQuark = attributeQuark;
86 fName = seriesName;
87 }
88
89 public double[] getYValues() {
90 return fYValues;
91 }
92
93 public Integer getDisplayQuark() {
94 return fDisplayQuark;
95 }
96
97 public String getSeriesName() {
98 return fName;
99 }
100
101 public void setYValue(int i, double yvalue) {
102 fYValues[i] = yvalue;
103 }
104 }
105
106 private class XmlXYEntry implements IXmlStateSystemContainer {
107
108 private final ITmfStateSystem fStateSystem;
109 private final String fPath;
110
111 public XmlXYEntry(ITmfStateSystem stateSystem, String path) {
112 fStateSystem = stateSystem;
113 fPath = path;
114 }
115
116 @Override
117 public @Nullable String getAttributeValue(@Nullable String name) {
118 return name;
119 }
120
121 @Override
122 public ITmfStateSystem getStateSystem() {
123 return fStateSystem;
124 }
125
126 @Override
127 public @Nullable Iterable<TmfXmlLocation> getLocations() {
128 return Collections.EMPTY_SET;
129 }
130
131 public List<Integer> getQuarks() {
132 /* Get the list of quarks to process with this path */
133 String[] paths = fPath.split(SPLIT_STRING);
134 @SuppressWarnings("null")
135 @NonNull List<Integer> quarks = Collections.singletonList(IXmlStateSystemContainer.ROOT_QUARK);
136
137 try {
138 for (String path : paths) {
139 List<Integer> subQuarks = new LinkedList<>();
140 /* Replace * by .* to have a regex string */
141 String name = WILDCARD_PATTERN.matcher(path).replaceAll(".*"); //$NON-NLS-1$
142 for (int relativeQuark : quarks) {
143 subQuarks.addAll(fStateSystem.getSubAttributes(relativeQuark, false, name));
144 }
145 quarks = subQuarks;
146 }
147 } catch (AttributeNotFoundException e) {
148 /*
149 * We get all attributes from the state system itself, this
150 * should not happen.
151 */
152 throw new IllegalStateException();
153 }
154 return quarks;
155 }
156 }
157
158 /**
159 * Constructor
160 *
161 * @param parent
162 * parent view
163 * @param viewInfo
164 * The view info object
165 */
166 public XmlXYViewer(@Nullable Composite parent, XmlViewInfo viewInfo) {
167 super(parent, Messages.XmlXYViewer_DefaultViewerTitle, Messages.XmlXYViewer_DefaultXAxis, Messages.XmlXYViewer_DefaultYAxis);
168 fViewInfo = viewInfo;
169 }
170
171 @Override
172 protected void updateData(long start, long end, int nb, @Nullable IProgressMonitor monitor) {
173
174 ITmfXmlStateAttribute display = fDisplay;
175 ITmfXmlStateAttribute seriesNameAttrib = fSeriesName;
176 XmlXYEntry entry = fEntry;
177 if (getTrace() == null || display == null || entry == null) {
178 return;
179 }
180 ITmfStateSystem ss = entry.getStateSystem();
181
182 double[] xvalues = getXAxis(start, end, nb);
183 setXAxis(xvalues);
184
185 boolean complete = false;
186 long currentEnd = start;
187
188 while (!complete && currentEnd < end) {
189 if (monitor != null && monitor.isCanceled()) {
190 return;
191 }
192
aa9b2552 193 complete = ss.waitUntilBuilt(TmfUiRefreshHandler.UPDATE_PERIOD);
87c5447c
GB
194 currentEnd = ss.getCurrentEndTime();
195 try {
196 List<Integer> quarks = entry.getQuarks();
197 long traceStart = getStartTime();
198 long traceEnd = getEndTime();
199 long offset = this.getTimeOffset();
200
201 /* Initialize quarks and series names */
202 for (int quark : quarks) {
203 String seriesName = null;
204 if (seriesNameAttrib == null) {
205 seriesName = ss.getAttributeName(quark);
206 } else {
207 int seriesNameQuark = seriesNameAttrib.getAttributeQuark(quark);
208 try {
209 ITmfStateValue seriesNameValue = ss.querySingleState(start, seriesNameQuark).getStateValue();
210 if (!seriesNameValue.isNull()) {
211 seriesName = seriesNameValue.unboxStr();
212 }
213 if (seriesName == null || seriesName.isEmpty()) {
214 seriesName = ss.getAttributeName(quark);
215 }
216 } catch (TimeRangeException e) {
217 /*
218 * The attribute did not exist at this point, simply
219 * use attribute name as series name
220 */
221 seriesName = ss.getAttributeName(quark);
222 }
223 }
224 if (seriesName == null) {
225 throw new IllegalStateException();
226 }
227 fSeriesData.put(quark, new SeriesData(xvalues.length, display.getAttributeQuark(quark), seriesName));
228 }
229 double yvalue = 0.0;
230 for (int i = 0; i < xvalues.length; i++) {
231 if (monitor != null && monitor.isCanceled()) {
232 return;
233 }
234 double x = xvalues[i];
235 long time = (long) x + offset;
236 // make sure that time is in the trace range after double to
237 // long conversion
238 time = time < traceStart ? traceStart : time;
239 time = time > traceEnd ? traceEnd : time;
240
241 for (int quark : quarks) {
242 try {
243 yvalue = ss.querySingleState(time, fSeriesData.get(quark).getDisplayQuark()).getStateValue().unboxLong();
244 fSeriesData.get(quark).setYValue(i, yvalue);
245 } catch (TimeRangeException e) {
246 fSeriesData.get(quark).setYValue(i, 0);
247 }
248 }
249 }
250 for (int quark : quarks) {
251 setSeries(fSeriesData.get(quark).getSeriesName(), fSeriesData.get(quark).getYValues());
252 }
253 updateDisplay();
254 } catch (AttributeNotFoundException | StateValueTypeException e) {
255 Activator.logError("Error updating the data of XML XY view", e); //$NON-NLS-1$
256 } catch (StateSystemDisposedException e) {
257 return;
258 }
259 }
260
261 }
262
263 @Override
264 protected void initializeDataSource() {
265 super.initializeDataSource();
266
267 ITmfTrace trace = this.getTrace();
268 if (trace == null) {
269 return;
270 }
271
272 Element viewElement = fViewInfo.getViewElement(TmfXmlUiStrings.XY_VIEW);
273 if (viewElement == null) {
274 return;
275 }
276
277 Iterable<String> analysisIds = fViewInfo.getViewAnalysisIds(viewElement);
278
279 List<ITmfAnalysisModuleWithStateSystems> stateSystemModules = new LinkedList<>();
280 if (!analysisIds.iterator().hasNext()) {
281 /*
282 * No analysis specified, take all state system analysis modules
283 */
284 for (ITmfAnalysisModuleWithStateSystems module : trace.getAnalysisModulesOfClass(ITmfAnalysisModuleWithStateSystems.class)) {
285 stateSystemModules.add(module);
286 }
287 } else {
288 for (String moduleId : analysisIds) {
289 @SuppressWarnings("resource")
290 ITmfAnalysisModuleWithStateSystems module = trace.getAnalysisModuleOfClass(ITmfAnalysisModuleWithStateSystems.class, moduleId);
291 if (module != null) {
292 stateSystemModules.add(module);
293 }
294 }
295 }
296
297 /** Initialize the data */
298 fDisplay = null;
299 fSeriesName = null;
300 ITmfStateSystem ss = null;
301 fEntry = null;
302
303 /* Schedule all state systems */
304 for (ITmfAnalysisModuleWithStateSystems module : stateSystemModules) {
305 module.schedule();
306 if (module instanceof TmfStateSystemAnalysisModule) {
307 ((TmfStateSystemAnalysisModule) module).waitForInitialization();
308 }
309 for (ITmfStateSystem ssq : module.getStateSystems()) {
310 if (ssq != null) {
311 ss = ssq;
312 break;
313 }
314 }
315 }
316 if (ss == null) {
317 return;
318 }
319
320 /*
321 * Initialize state attributes. There should be only one entry element
322 * for XY charts.
323 */
324 List<Element> entries = XmlUtils.getChildElements(viewElement, TmfXmlUiStrings.ENTRY_ELEMENT);
325 Element entryElement = entries.get(0);
326 String path = entryElement.getAttribute(TmfXmlUiStrings.PATH);
327 if (path.isEmpty()) {
328 path = TmfXmlStrings.WILDCARD;
329 }
330 XmlXYEntry entry = new XmlXYEntry(ss, path);
331 fEntry = entry;
332
333 /* Get the display element to use */
334 List<Element> displayElements = XmlUtils.getChildElements(entryElement, TmfXmlUiStrings.DISPLAY_ELEMENT);
335 if (displayElements.isEmpty()) {
336 Activator.logWarning(String.format("XML view: entry for %s should have a display element", path)); //$NON-NLS-1$
337 return;
338 }
339 Element displayElement = displayElements.get(0);
340 fDisplay = fFactory.createStateAttribute(displayElement, entry);
341
342 /* Get the series name element to use */
343 List<Element> seriesNameElements = XmlUtils.getChildElements(entryElement, TmfXmlUiStrings.NAME_ELEMENT);
344 if (!seriesNameElements.isEmpty()) {
345 Element seriesNameElement = seriesNameElements.get(0);
346 fSeriesName = fFactory.createStateAttribute(seriesNameElement, entry);
347 }
348
349 }
350
351 /**
352 * Tells the viewer that the view info has been updated and the viewer needs
353 * to be reinitialized
354 */
355 public void viewInfoUpdated() {
356 reinitialize();
357 }
358
359}
This page took 0.038106 seconds and 5 git commands to generate.