1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 Ericsson
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
10 * Alexandre Montplaisir - Initial API and implementation
11 * Patrick Tasse - Add support for folder elements
12 * Bernd Hufmann - Update trace type auto-detection
13 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
;
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
;
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
;
50 * Utils class for the UI-specific parts of @link {@link TmfTraceType}.
52 * @author Alexandre Montplaisir
54 public final class TmfTraceTypeUIUtils
{
56 /** Extension point ID */
57 public static final String TMF_TRACE_TYPE_UI_ID
= "org.eclipse.linuxtools.tmf.ui.tracetypeui"; //$NON-NLS-1$
59 /** Extension point element 'type' (should match the type in TmfTraceType) */
60 public static final String TYPE_ELEM
= "type"; //$NON-NLS-1$
63 * Extension point element 'experiment' (should match the type in
66 public static final String EXPERIMENT_ELEM
= "experiment"; //$NON-NLS-1$
68 /** Extension point element 'Default editor' */
69 public static final String DEFAULT_EDITOR_ELEM
= "defaultEditor"; //$NON-NLS-1$
71 /** Extension point element 'Events table type' */
72 public static final String EVENTS_TABLE_TYPE_ELEM
= "eventsTableType"; //$NON-NLS-1$
74 /** Extension point element 'Event Table Columns' */
75 public static final String EVENT_TABLE_COLUMNS
= "eventTableColumns"; //$NON-NLS-1$
77 /** Extension point element 'perspective'
79 public static final String PERSPECTIVE_ELEM
= "perspective"; //$NON-NLS-1$
81 /** Extension point attribute 'id'
83 public static final String ID_ATTR
= "id"; //$NON-NLS-1$
85 /** Extension point attribute 'tracetype' */
86 public static final String TRACETYPE_ATTR
= "tracetype"; //$NON-NLS-1$
88 /** Extension point attribute 'icon' */
89 public static final String ICON_ATTR
= "icon"; //$NON-NLS-1$
91 /** Extension point attribute 'class' (attribute of other elements) */
92 public static final String CLASS_ATTR
= "class"; //$NON-NLS-1$
94 private TmfTraceTypeUIUtils() {
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());
108 b
.addSelectionListener(new SelectionListener() {
111 public void widgetSelected(SelectionEvent e
) {
112 final Button source
= (Button
) e
.getSource();
113 candidatesToSet
[0] = (names
.get(source
.getText()));
114 source
.getParent().dispose();
118 public void widgetDefaultSelected(SelectionEvent e
) {
123 shellToShow
.setLayout(new RowLayout(SWT
.VERTICAL
));
127 Display display
= shellToShow
.getDisplay();
128 while (!shellToShow
.isDisposed()) {
129 if (!display
.readAndDispatch()) {
133 return TmfTraceType
.getTraceType(candidatesToSet
[0]);
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.
141 * The path of trace to import (file or directory for directory
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
154 public static @Nullable TraceTypeHelper
selectTraceType(String path
, Shell shell
, String traceTypeHint
) throws TmfTraceImportException
{
155 List
<TraceTypeHelper
> candidates
= TmfTraceType
.selectTraceType(path
, traceTypeHint
);
157 if (candidates
.isEmpty()) {
161 if ((candidates
.size() == 1) || (shell
== null)) {
162 return candidates
.get(0);
165 return getTraceTypeToSet(candidates
, shell
);
169 * Set the trace type of a {@link TraceTypeHelper}. Should only be
170 * used internally by this project.
173 * the resource to set
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.
180 public static IStatus
setTraceType(IResource resource
, TraceTypeHelper traceType
) throws CoreException
{
181 return setTraceType(resource
, traceType
, true);
185 * Set the trace type of a {@link TraceTypeHelper}. Should only be
186 * used internally by this project.
189 * the resource to set
191 * the {@link TraceTypeHelper} to set the trace type to.
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.
198 public static IStatus
setTraceType(IResource resource
, TraceTypeHelper traceType
, boolean refresh
) throws CoreException
{
199 String traceTypeId
= traceType
.getTraceTypeId();
201 resource
.setPersistentProperty(TmfCommonConstants
.TRACETYPE
, traceTypeId
);
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();
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
);
225 tmfProject
.refresh();
227 return Status
.OK_STATUS
;
230 private static void refreshTraceElement(List
<TmfTraceElement
> traceElements
, String elementPath
) {
231 for (TmfTraceElement traceElement
: traceElements
) {
232 if (traceElement
.getElementPath().equals(elementPath
)) {
233 traceElement
.refreshTraceType();
240 * Retrieves all configuration elements from the platform extension registry
241 * for the trace type UI extension.
244 * The type of trace type requested, either TRACE or EXPERIMENT
245 * @return An array of trace type configuration elements
247 public static IConfigurationElement
[] getTypeUIElements(TraceElementType elType
) {
248 String elementName
= TYPE_ELEM
;
249 if (elType
== TraceElementType
.EXPERIMENT
) {
250 elementName
= EXPERIMENT_ELEM
;
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
);
260 return typeElements
.toArray(new IConfigurationElement
[typeElements
.size()]);
264 * Get the UI elements for the given trace type
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.
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
))) {
285 * Get the Event Table type specified by the trace type's extension point,
289 * The trace for which we want the events table.
291 * The parent composite that the event table will have
293 * The cache size to use with this event table. Should be defined
295 * @return The corresponding Event Table, or 'null' if this trace type did
298 public static @Nullable TmfEventsTable
getEventTable(ITmfTrace trace
, Composite parent
, int cacheSize
) {
299 final String traceType
= getTraceType(trace
);
300 if (traceType
== null) {
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
);
309 if (eventsTableTypeCE
.length
!= 1) {
312 final String eventsTableType
= eventsTableTypeCE
[0].getAttribute(TmfTraceTypeUIUtils
.CLASS_ATTR
);
313 if (eventsTableType
.isEmpty()) {
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
);
324 } catch (NoSuchMethodException
| ClassNotFoundException
| InstantiationException
|
325 IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e
) {
334 * Get the perspective id specified by the trace type's extension point, if
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.
343 public static @Nullable String
getPerspectiveId(ITmfTrace trace
) {
344 final String traceType
= getTraceType(trace
);
345 if (traceType
== null) {
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
);
354 if (perspectiveCE
.length
!= 1) {
357 final String perspectiveId
= perspectiveCE
[0].getAttribute(ID_ATTR
);
358 if (!perspectiveId
.isEmpty()) {
359 return perspectiveId
;
368 * Get the trace type (as a String) for the given trace
372 * @return The String representing the trace type, or 'null' if this trace
373 * does not advertise it.
375 private static @Nullable String
getTraceType(ITmfTrace trace
) {
376 IResource res
= trace
.getResource();
381 String traceType
= res
.getPersistentProperty(TmfCommonConstants
.TRACETYPE
);
382 /* May be null here too */
385 } catch (CoreException e
) {