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