Tmf: Add the experiment type to the trace type extension point
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / project / model / TmfTraceTypeUIUtils.java
1 /*******************************************************************************
2 * Copyright (c) 2014 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 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.ui.project.model;
14
15 import java.util.ArrayList;
16 import java.util.Comparator;
17 import java.util.HashMap;
18 import java.util.LinkedList;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.TreeSet;
22
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IConfigurationElement;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.Platform;
28 import org.eclipse.core.runtime.Status;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
31 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceImportException;
32 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
33 import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
34 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
35 import org.eclipse.linuxtools.tmf.core.util.Pair;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.SelectionListener;
39 import org.eclipse.swt.layout.RowLayout;
40 import org.eclipse.swt.widgets.Button;
41 import org.eclipse.swt.widgets.Display;
42 import org.eclipse.swt.widgets.Shell;
43
44 /**
45 * Utils class for the UI-specific parts of @link {@link TmfTraceType}.
46 *
47 * @author Alexandre Montplaisir
48 * @since 3.0
49 */
50 public final class TmfTraceTypeUIUtils {
51
52 /** Extension point ID */
53 public static final String TMF_TRACE_TYPE_UI_ID = "org.eclipse.linuxtools.tmf.ui.tracetypeui"; //$NON-NLS-1$
54
55 /** Extension point element 'type' (should match the type in TmfTraceType) */
56 public static final String TYPE_ELEM = "type"; //$NON-NLS-1$
57
58 /**
59 * Extension point element 'experiment' (should match the type in
60 * TmfTraceType)
61 */
62 public static final String EXPERIMENT_ELEM = "experiment"; //$NON-NLS-1$
63
64 /** Extension point element 'Default editor' */
65 public static final String DEFAULT_EDITOR_ELEM = "defaultEditor"; //$NON-NLS-1$
66
67 /** Extension point element 'Events table type' */
68 public static final String EVENTS_TABLE_TYPE_ELEM = "eventsTableType"; //$NON-NLS-1$
69
70 /** Extension point attribute 'tracetype' */
71 public static final String TRACETYPE_ATTR = "tracetype"; //$NON-NLS-1$
72
73 /** Extension point attribute 'icon' */
74 public static final String ICON_ATTR = "icon"; //$NON-NLS-1$
75
76 /** Extension point attribute 'class' (attribute of eventsTableType) */
77 public static final String CLASS_ATTR = "class"; //$NON-NLS-1$
78
79 private static final char SEPARATOR = ':';
80
81 private TmfTraceTypeUIUtils() {}
82
83 private static List<Pair<Integer, TraceTypeHelper>> reduce(List<Pair<Integer, TraceTypeHelper>> candidates) {
84 List<Pair<Integer, TraceTypeHelper>> retVal = new ArrayList<>();
85
86 // get all the tracetypes that are unique in that stage
87 for (Pair<Integer, TraceTypeHelper> candidatePair : candidates) {
88 TraceTypeHelper candidate = candidatePair.getSecond();
89 if (isUnique(candidate, candidates)) {
90 retVal.add(candidatePair);
91 }
92 }
93 return retVal;
94 }
95
96 /*
97 * Only return the leaves of the trace types. Ignore custom trace types.
98 */
99 private static boolean isUnique(TraceTypeHelper trace, List<Pair<Integer, TraceTypeHelper>> set) {
100 if (isCustomTraceId(trace.getCanonicalName())) {
101 return true;
102 }
103 // check if the trace type is the leaf. we make an instance of the trace
104 // type and if it is only an instance of itself, it is a leaf
105 final ITmfTrace tmfTrace = trace.getTrace();
106 int count = -1;
107 for (Pair<Integer, TraceTypeHelper> child : set) {
108 final ITmfTrace traceCandidate = child.getSecond().getTrace();
109 if (tmfTrace.getClass().isInstance(traceCandidate)) {
110 count++;
111 }
112 }
113 return count == 0;
114 }
115
116
117 /**
118 * Is the trace type id a custom (user-defined) trace type. These are the
119 * traces like : text and xml defined by the custom trace wizard.
120 *
121 * @param traceTypeId
122 * the trace type id
123 * @return true if the trace is a custom type
124 */
125 private static boolean isCustomTraceId(String traceTypeId) {
126 TraceTypeHelper traceType = TmfTraceType.getInstance().getTraceType(traceTypeId);
127 if (traceType != null) {
128 return TmfTraceType.isCustomTrace(traceType.getCategoryName() + SEPARATOR + traceType.getName());
129 }
130 return false;
131 }
132
133 private static TraceTypeHelper getTraceTypeToSet(TmfTraceType type, List<Pair<Integer, TraceTypeHelper>> candidates, Shell shell) {
134 final Map<String, String> names = new HashMap<>();
135 Shell shellToShow = new Shell(shell);
136 shellToShow.setText(Messages.TmfTraceType_SelectTraceType);
137 final String candidatesToSet[] = new String[1];
138 for (Pair<Integer, TraceTypeHelper> candidatePair : candidates) {
139 TraceTypeHelper candidate = candidatePair.getSecond();
140 Button b = new Button(shellToShow, SWT.RADIO);
141 final String displayName = candidate.getCategoryName() + ':' + candidate.getName();
142 b.setText(displayName);
143 names.put(displayName, candidate.getCanonicalName());
144
145 b.addSelectionListener(new SelectionListener() {
146
147 @Override
148 public void widgetSelected(SelectionEvent e) {
149 final Button source = (Button) e.getSource();
150 candidatesToSet[0] = (names.get(source.getText()));
151 source.getParent().dispose();
152 }
153
154 @Override
155 public void widgetDefaultSelected(SelectionEvent e) {
156
157 }
158 });
159 }
160 shellToShow.setLayout(new RowLayout(SWT.VERTICAL));
161 shellToShow.pack();
162 shellToShow.open();
163
164 Display display = shellToShow.getDisplay();
165 while (!shellToShow.isDisposed()) {
166 if (!display.readAndDispatch()) {
167 display.sleep();
168 }
169 }
170 return type.getTraceTypeHelper(candidatesToSet[0]);
171 }
172
173 /**
174 * This member figures out the trace type of a given file. It will prompt
175 * the user if it needs more information to properly pick the trace type.
176 *
177 * @param path
178 * The path of file to import
179 * @param shell
180 * a shell to display the message to. If it is null, it is
181 * assumed to be cancelled.
182 * @param traceTypeHint
183 * the ID of a trace (like "o.e.l.specifictrace" )
184 * @return null if the request is cancelled or a TraceTypeHelper if it
185 * passes.
186 * @throws TmfTraceImportException
187 * if the traces don't match or there are errors in the trace
188 * file
189 */
190 public static TraceTypeHelper selectTraceType(String path, Shell shell, String traceTypeHint) throws TmfTraceImportException {
191 TmfTraceType type = TmfTraceType.getInstance();
192
193 Comparator<Pair<Integer, TraceTypeHelper>> comparator = new Comparator<Pair<Integer, TraceTypeHelper>>() {
194 @Override
195 public int compare(Pair<Integer, TraceTypeHelper> o1, Pair<Integer, TraceTypeHelper> o2) {
196 int res = -o1.getFirst().compareTo(o2.getFirst()); // invert so that highest confidence is first
197 if (res == 0) {
198 res = o1.getSecond().getName().compareTo(o2.getSecond().getName());
199 }
200 return res;
201 }
202 };
203 TreeSet<Pair<Integer, TraceTypeHelper>> validCandidates = new TreeSet<>(comparator);
204 final Iterable<TraceTypeHelper> traceTypeHelpers = type.getTraceTypeHelpers();
205 for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) {
206 int confidence = traceTypeHelper.validateWithConfidence(path);
207 if (confidence >= 0) {
208 // insert in the tree map, ordered by confidence (highest confidence first) then name
209 Pair<Integer, TraceTypeHelper> element = new Pair<>(confidence, traceTypeHelper);
210 validCandidates.add(element);
211 }
212 }
213
214 TraceTypeHelper traceTypeToSet = null;
215 if (validCandidates.isEmpty()) {
216 final String errorMsg = Messages.TmfOpenTraceHelper_NoTraceTypeMatch + path;
217 throw new TmfTraceImportException(errorMsg);
218 } else if (validCandidates.size() != 1) {
219 List<Pair<Integer, TraceTypeHelper>> candidates = new ArrayList<>(validCandidates);
220 List<Pair<Integer, TraceTypeHelper>> reducedCandidates = reduce(candidates);
221 for (Pair<Integer, TraceTypeHelper> candidatePair : reducedCandidates) {
222 TraceTypeHelper candidate = candidatePair.getSecond();
223 if (candidate.getCanonicalName().equals(traceTypeHint)) {
224 traceTypeToSet = candidate;
225 break;
226 }
227 }
228 if (traceTypeToSet == null) {
229 if (reducedCandidates.size() == 0) {
230 throw new TmfTraceImportException(Messages.TmfOpenTraceHelper_ReduceError);
231 } else if (reducedCandidates.size() == 1) {
232 traceTypeToSet = reducedCandidates.get(0).getSecond();
233 } else if (shell == null) {
234 Pair<Integer, TraceTypeHelper> candidate = reducedCandidates.get(0);
235 // if the best match has lowest confidence, don't select it
236 if (candidate.getFirst() > 0) {
237 traceTypeToSet = candidate.getSecond();
238 }
239 } else {
240 traceTypeToSet = getTraceTypeToSet(type, reducedCandidates, shell);
241 }
242 }
243 } else {
244 traceTypeToSet = validCandidates.first().getSecond();
245 }
246 return traceTypeToSet;
247 }
248
249
250 /**
251 * Set the trace type of a {@Link TraceTypeHelper}. Should only be
252 * used internally by this project.
253 *
254 * @param resource
255 * the resource to set
256 * @param traceType
257 * the {@link TraceTypeHelper} to set the trace type to.
258 * @return Status.OK_Status if successful, error is otherwise.
259 * @throws CoreException
260 * An exception caused by accessing eclipse project items.
261 */
262 public static IStatus setTraceType(IResource resource, TraceTypeHelper traceType) throws CoreException {
263 String traceTypeId = traceType.getCanonicalName();
264
265 resource.setPersistentProperty(TmfCommonConstants.TRACETYPE, traceTypeId);
266
267 TmfProjectElement tmfProject = TmfProjectRegistry.getProject(resource.getProject(), true);
268 if (resource.getParent().equals(tmfProject.getTracesFolder().getResource())) {
269 refreshTraceElement(tmfProject.getTracesFolder().getTraces(), resource.getName());
270 } else {
271 for (TmfExperimentElement experimentElement : tmfProject.getExperimentsFolder().getExperiments()) {
272 if (resource.getParent().equals(experimentElement.getResource())) {
273 refreshTraceElement(experimentElement.getTraces(), resource.getName());
274 break;
275 }
276 }
277 }
278 tmfProject.refresh();
279 return Status.OK_STATUS;
280 }
281
282 private static void refreshTraceElement(List<TmfTraceElement> traceElements, String traceName) {
283 for (TmfTraceElement traceElement : traceElements) {
284 if (traceElement.getName().equals(traceName)) {
285 traceElement.refreshTraceType();
286 break;
287 }
288 }
289 }
290
291 /**
292 * Retrieves all configuration elements from the platform extension registry
293 * for the trace type UI extension.
294 *
295 * @return An array of trace type configuration elements
296 */
297 public static IConfigurationElement[] getTypeUIElements() {
298 IConfigurationElement[] elements =
299 Platform.getExtensionRegistry().getConfigurationElementsFor(TMF_TRACE_TYPE_UI_ID);
300 List<IConfigurationElement> typeElements = new LinkedList<>();
301 for (IConfigurationElement element : elements) {
302 if (element.getName().equals(TYPE_ELEM)) {
303 typeElements.add(element);
304 }
305 }
306 return typeElements.toArray(new IConfigurationElement[typeElements.size()]);
307 }
308
309 /**
310 * Get the UI elements for the given trace type
311 *
312 * @param traceType
313 * The tracetype ID
314 * @return The top-level configuration element (access its children with
315 * .getChildren()). Or null if there is no such element.
316 */
317 @Nullable
318 public static IConfigurationElement getTraceUIAttributes(String traceType) {
319 IConfigurationElement[] elements = getTypeUIElements();
320 for (IConfigurationElement ce : elements) {
321 if (traceType.equals(ce.getAttribute(TRACETYPE_ATTR))) {
322 return ce;
323 }
324 }
325 return null;
326 }
327 }
This page took 0.039394 seconds and 6 git commands to generate.