tmf: Add perspective element to trace type UI extension point
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / project / model / TmfTraceTypeUIUtils.java
1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 Ericsson
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 * Alexandre Montplaisir - Initial API and implementation
11 * Patrick Tasse - Add support for folder elements
12 * Bernd Hufmann - Update trace type auto-detection
13 *******************************************************************************/
14
15 package org.eclipse.tracecompass.tmf.ui.project.model;
16
17 import java.lang.reflect.Constructor;
18 import java.lang.reflect.InvocationTargetException;
19 import java.util.HashMap;
20 import java.util.LinkedList;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IConfigurationElement;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.Platform;
29 import org.eclipse.core.runtime.Status;
30 import org.eclipse.jdt.annotation.Nullable;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.events.SelectionEvent;
33 import org.eclipse.swt.events.SelectionListener;
34 import org.eclipse.swt.layout.RowLayout;
35 import org.eclipse.swt.widgets.Button;
36 import org.eclipse.swt.widgets.Composite;
37 import org.eclipse.swt.widgets.Display;
38 import org.eclipse.swt.widgets.Shell;
39 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
40 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
41 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
42 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType.TraceElementType;
43 import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
44 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
45 import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
46 import org.eclipse.tracecompass.tmf.ui.viewers.events.TmfEventsTable;
47 import org.osgi.framework.Bundle;
48
49 /**
50 * Utils class for the UI-specific parts of @link {@link TmfTraceType}.
51 *
52 * @author Alexandre Montplaisir
53 */
54 public final class TmfTraceTypeUIUtils {
55
56 /** Extension point ID */
57 public static final String TMF_TRACE_TYPE_UI_ID = "org.eclipse.linuxtools.tmf.ui.tracetypeui"; //$NON-NLS-1$
58
59 /** Extension point element 'type' (should match the type in TmfTraceType) */
60 public static final String TYPE_ELEM = "type"; //$NON-NLS-1$
61
62 /**
63 * Extension point element 'experiment' (should match the type in
64 * TmfTraceType)
65 */
66 public static final String EXPERIMENT_ELEM = "experiment"; //$NON-NLS-1$
67
68 /** Extension point element 'Default editor' */
69 public static final String DEFAULT_EDITOR_ELEM = "defaultEditor"; //$NON-NLS-1$
70
71 /** Extension point element 'Events table type' */
72 public static final String EVENTS_TABLE_TYPE_ELEM = "eventsTableType"; //$NON-NLS-1$
73
74 /** Extension point element 'Event Table Columns' */
75 public static final String EVENT_TABLE_COLUMNS = "eventTableColumns"; //$NON-NLS-1$
76
77 /** Extension point element 'perspective'
78 * @since 2.3*/
79 public static final String PERSPECTIVE_ELEM = "perspective"; //$NON-NLS-1$
80
81 /** Extension point attribute 'id'
82 * @since 2.3*/
83 public static final String ID_ATTR = "id"; //$NON-NLS-1$
84
85 /** Extension point attribute 'tracetype' */
86 public static final String TRACETYPE_ATTR = "tracetype"; //$NON-NLS-1$
87
88 /** Extension point attribute 'icon' */
89 public static final String ICON_ATTR = "icon"; //$NON-NLS-1$
90
91 /** Extension point attribute 'class' (attribute of other elements) */
92 public static final String CLASS_ATTR = "class"; //$NON-NLS-1$
93
94 private TmfTraceTypeUIUtils() {
95 }
96
97 private static TraceTypeHelper getTraceTypeToSet(List<TraceTypeHelper> candidates, Shell shell) {
98 final Map<String, String> names = new HashMap<>();
99 Shell shellToShow = new Shell(shell);
100 shellToShow.setText(Messages.TmfTraceType_SelectTraceType);
101 final String candidatesToSet[] = new String[1];
102 for (TraceTypeHelper candidate : candidates) {
103 Button b = new Button(shellToShow, SWT.RADIO);
104 final String displayName = candidate.getCategoryName() + ':' + candidate.getName();
105 b.setText(displayName);
106 names.put(displayName, candidate.getTraceTypeId());
107
108 b.addSelectionListener(new SelectionListener() {
109
110 @Override
111 public void widgetSelected(SelectionEvent e) {
112 final Button source = (Button) e.getSource();
113 candidatesToSet[0] = (names.get(source.getText()));
114 source.getParent().dispose();
115 }
116
117 @Override
118 public void widgetDefaultSelected(SelectionEvent e) {
119
120 }
121 });
122 }
123 shellToShow.setLayout(new RowLayout(SWT.VERTICAL));
124 shellToShow.pack();
125 shellToShow.open();
126
127 Display display = shellToShow.getDisplay();
128 while (!shellToShow.isDisposed()) {
129 if (!display.readAndDispatch()) {
130 display.sleep();
131 }
132 }
133 return TmfTraceType.getTraceType(candidatesToSet[0]);
134 }
135
136 /**
137 * This member figures out the trace type of a given trace. It will prompt
138 * the user if it needs more information to properly pick the trace type.
139 *
140 * @param path
141 * The path of trace to import (file or directory for directory
142 * traces)
143 * @param shell
144 * a shell to query user in case of multiple valid trace types.
145 * If it is null, than the first one alphabetically is selected.
146 * @param traceTypeHint
147 * the ID of a trace (like "o.e.l.specifictrace" )
148 * @return {@link TraceTypeHelper} for valid trace type or null if no valid
149 * trace type was found in case of single file trace
150 * @throws TmfTraceImportException
151 * if there are errors in the trace file or no trace type found
152 * for a directory trace
153 */
154 public static @Nullable TraceTypeHelper selectTraceType(String path, Shell shell, String traceTypeHint) throws TmfTraceImportException {
155 List<TraceTypeHelper> candidates = TmfTraceType.selectTraceType(path, traceTypeHint);
156
157 if (candidates.isEmpty()) {
158 return null;
159 }
160
161 if ((candidates.size() == 1) || (shell == null)) {
162 return candidates.get(0);
163 }
164
165 return getTraceTypeToSet(candidates, shell);
166 }
167
168 /**
169 * Set the trace type of a {@link TraceTypeHelper}. Should only be
170 * used internally by this project.
171 *
172 * @param resource
173 * the resource to set
174 * @param traceType
175 * the {@link TraceTypeHelper} to set the trace type to.
176 * @return Status.OK_Status if successful, error is otherwise.
177 * @throws CoreException
178 * An exception caused by accessing eclipse project items.
179 */
180 public static IStatus setTraceType(IResource resource, TraceTypeHelper traceType) throws CoreException {
181 return setTraceType(resource, traceType, true);
182 }
183
184 /**
185 * Set the trace type of a {@link TraceTypeHelper}. Should only be
186 * used internally by this project.
187 *
188 * @param resource
189 * the resource to set
190 * @param traceType
191 * the {@link TraceTypeHelper} to set the trace type to.
192 * @param refresh
193 * Flag for refreshing the project
194 * @return Status.OK_Status if successful, error is otherwise.
195 * @throws CoreException
196 * An exception caused by accessing eclipse project items.
197 */
198 public static IStatus setTraceType(IResource resource, TraceTypeHelper traceType, boolean refresh) throws CoreException {
199 String traceTypeId = traceType.getTraceTypeId();
200
201 resource.setPersistentProperty(TmfCommonConstants.TRACETYPE, traceTypeId);
202
203 TmfProjectElement tmfProject = TmfProjectRegistry.getProject(resource.getProject(), true);
204 if (tmfProject.getTracesFolder().getPath().isPrefixOf(resource.getFullPath())) {
205 String elementPath = resource.getFullPath().makeRelativeTo(tmfProject.getTracesFolder().getPath()).toString();
206 refreshTraceElement(tmfProject.getTracesFolder().getTraces(), elementPath);
207 } else if (resource.getParent().equals(tmfProject.getExperimentsFolder().getResource())) {
208 /* The trace type to set is for an experiment */
209 for (TmfExperimentElement experimentElement : tmfProject.getExperimentsFolder().getExperiments()) {
210 if (resource.equals(experimentElement.getResource())) {
211 experimentElement.refreshTraceType();
212 break;
213 }
214 }
215 } else {
216 for (TmfExperimentElement experimentElement : tmfProject.getExperimentsFolder().getExperiments()) {
217 if (experimentElement.getPath().isPrefixOf(resource.getFullPath())) {
218 String elementPath = resource.getFullPath().makeRelativeTo(experimentElement.getPath()).toString();
219 refreshTraceElement(experimentElement.getTraces(), elementPath);
220 break;
221 }
222 }
223 }
224 if (refresh) {
225 tmfProject.refresh();
226 }
227 return Status.OK_STATUS;
228 }
229
230 private static void refreshTraceElement(List<TmfTraceElement> traceElements, String elementPath) {
231 for (TmfTraceElement traceElement : traceElements) {
232 if (traceElement.getElementPath().equals(elementPath)) {
233 traceElement.refreshTraceType();
234 break;
235 }
236 }
237 }
238
239 /**
240 * Retrieves all configuration elements from the platform extension registry
241 * for the trace type UI extension.
242 *
243 * @param elType
244 * The type of trace type requested, either TRACE or EXPERIMENT
245 * @return An array of trace type configuration elements
246 */
247 public static IConfigurationElement[] getTypeUIElements(TraceElementType elType) {
248 String elementName = TYPE_ELEM;
249 if (elType == TraceElementType.EXPERIMENT) {
250 elementName = EXPERIMENT_ELEM;
251 }
252 IConfigurationElement[] elements =
253 Platform.getExtensionRegistry().getConfigurationElementsFor(TMF_TRACE_TYPE_UI_ID);
254 List<IConfigurationElement> typeElements = new LinkedList<>();
255 for (IConfigurationElement element : elements) {
256 if (element.getName().equals(elementName)) {
257 typeElements.add(element);
258 }
259 }
260 return typeElements.toArray(new IConfigurationElement[typeElements.size()]);
261 }
262
263 /**
264 * Get the UI elements for the given trace type
265 *
266 * @param traceType
267 * The tracetype ID
268 * @param elType
269 * The type of trace type requested, either TRACE or EXPERIMENT
270 * @return The top-level configuration element (access its children with
271 * .getChildren()). Or null if there is no such element.
272 */
273 @Nullable
274 public static IConfigurationElement getTraceUIAttributes(String traceType, TraceElementType elType) {
275 IConfigurationElement[] elements = getTypeUIElements(elType);
276 for (IConfigurationElement ce : elements) {
277 if (traceType.equals(ce.getAttribute(TRACETYPE_ATTR))) {
278 return ce;
279 }
280 }
281 return null;
282 }
283
284 /**
285 * Get the Event Table type specified by the trace type's extension point,
286 * if there is one.
287 *
288 * @param trace
289 * The trace for which we want the events table.
290 * @param parent
291 * The parent composite that the event table will have
292 * @param cacheSize
293 * The cache size to use with this event table. Should be defined
294 * by the trace type.
295 * @return The corresponding Event Table, or 'null' if this trace type did
296 * not specify any.
297 */
298 public static @Nullable TmfEventsTable getEventTable(ITmfTrace trace, Composite parent, int cacheSize) {
299 final String traceType = getTraceType(trace);
300 if (traceType == null) {
301 return null;
302 }
303
304 TraceElementType elType = (trace instanceof TmfExperiment) ? TraceElementType.EXPERIMENT : TraceElementType.TRACE;
305 for (final IConfigurationElement ce : TmfTraceTypeUIUtils.getTypeUIElements(elType)) {
306 if (ce.getAttribute(TmfTraceTypeUIUtils.TRACETYPE_ATTR).equals(traceType)) {
307 final IConfigurationElement[] eventsTableTypeCE = ce.getChildren(TmfTraceTypeUIUtils.EVENTS_TABLE_TYPE_ELEM);
308
309 if (eventsTableTypeCE.length != 1) {
310 break;
311 }
312 final String eventsTableType = eventsTableTypeCE[0].getAttribute(TmfTraceTypeUIUtils.CLASS_ATTR);
313 if (eventsTableType.isEmpty()) {
314 break;
315 }
316 try {
317 final Bundle bundle = Platform.getBundle(ce.getContributor().getName());
318 final Class<?> c = bundle.loadClass(eventsTableType);
319 final Class<?>[] constructorArgs = new Class[] { Composite.class, int.class };
320 final Constructor<?> constructor = c.getConstructor(constructorArgs);
321 final Object[] args = new Object[] { parent, cacheSize };
322 return (TmfEventsTable) constructor.newInstance(args);
323
324 } catch (NoSuchMethodException | ClassNotFoundException | InstantiationException |
325 IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
326 return null;
327 }
328 }
329 }
330 return null;
331 }
332
333 /**
334 * Get the perspective id specified by the trace type's extension point, if
335 * there is one.
336 *
337 * @param trace
338 * The trace for which we want the perspective id.
339 * @return The corresponding perspective id, or 'null' if this trace type
340 * did not specify any.
341 * @since 2.3
342 */
343 public static @Nullable String getPerspectiveId(ITmfTrace trace) {
344 final String traceType = getTraceType(trace);
345 if (traceType == null) {
346 return null;
347 }
348
349 TraceElementType elType = (trace instanceof TmfExperiment) ? TraceElementType.EXPERIMENT : TraceElementType.TRACE;
350 for (final IConfigurationElement ce : TmfTraceTypeUIUtils.getTypeUIElements(elType)) {
351 if (ce.getAttribute(TRACETYPE_ATTR).equals(traceType)) {
352 final IConfigurationElement[] perspectiveCE = ce.getChildren(PERSPECTIVE_ELEM);
353
354 if (perspectiveCE.length != 1) {
355 break;
356 }
357 final String perspectiveId = perspectiveCE[0].getAttribute(ID_ATTR);
358 if (!perspectiveId.isEmpty()) {
359 return perspectiveId;
360 }
361 break;
362 }
363 }
364 return null;
365 }
366
367 /**
368 * Get the trace type (as a String) for the given trace
369 *
370 * @param trace
371 * The trace object
372 * @return The String representing the trace type, or 'null' if this trace
373 * does not advertise it.
374 */
375 private static @Nullable String getTraceType(ITmfTrace trace) {
376 IResource res = trace.getResource();
377 if (res == null) {
378 return null;
379 }
380 try {
381 String traceType = res.getPersistentProperty(TmfCommonConstants.TRACETYPE);
382 /* May be null here too */
383 return traceType;
384
385 } catch (CoreException e) {
386 return null;
387 }
388 }
389 }
This page took 0.074216 seconds and 5 git commands to generate.