Commit | Line | Data |
---|---|---|
4bf17f4a | 1 | /******************************************************************************* |
281def42 | 2 | * Copyright (c) 2011, 2016 Ericsson, École Polytechnique de Montréal |
cfd22ad0 | 3 | * |
4bf17f4a | 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 | |
cfd22ad0 | 8 | * |
4bf17f4a | 9 | * Contributors: |
10 | * Patrick Tasse - Initial API and implementation | |
d04ec5a7 | 11 | * Matthew Khouzam - Added import functionalities |
1ec2ca01 | 12 | * Geneviève Bastien - Added support for experiment types |
c9b31f60 | 13 | * Bernd Hufmann - Updated custom trace type ID handling |
4bf17f4a | 14 | *******************************************************************************/ |
15 | ||
2bdf0193 | 16 | package org.eclipse.tracecompass.tmf.core.project.model; |
4bf17f4a | 17 | |
281def42 | 18 | import java.io.File; |
d04ec5a7 | 19 | import java.util.ArrayList; |
252c602c BH |
20 | import java.util.Collections; |
21 | import java.util.Comparator; | |
d04ec5a7 | 22 | import java.util.HashMap; |
d04ec5a7 | 23 | import java.util.LinkedHashMap; |
4bf17f4a | 24 | import java.util.LinkedList; |
25 | import java.util.List; | |
d04ec5a7 | 26 | import java.util.Map; |
88424bb7 | 27 | import java.util.Map.Entry; |
281def42 | 28 | import java.util.TreeSet; |
4bf17f4a | 29 | |
4b3b667b | 30 | import org.eclipse.core.resources.IResource; |
05627bda | 31 | import org.eclipse.core.runtime.CoreException; |
4bf17f4a | 32 | import org.eclipse.core.runtime.IConfigurationElement; |
d16bb0dd | 33 | import org.eclipse.core.runtime.IStatus; |
4bf17f4a | 34 | import org.eclipse.core.runtime.Platform; |
281def42 BH |
35 | import org.eclipse.jdt.annotation.NonNull; |
36 | import org.eclipse.osgi.util.NLS; | |
d77f31da | 37 | import org.eclipse.tracecompass.internal.tmf.core.Activator; |
281def42 | 38 | import org.eclipse.tracecompass.internal.tmf.core.project.model.Messages; |
2bdf0193 AM |
39 | import org.eclipse.tracecompass.tmf.core.TmfCommonConstants; |
40 | import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTrace; | |
41 | import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition; | |
42 | import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTrace; | |
43 | import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTraceDefinition; | |
44 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; | |
45 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
281def42 | 46 | import org.eclipse.tracecompass.tmf.core.util.Pair; |
4bf17f4a | 47 | |
b544077e | 48 | /** |
d04ec5a7 MK |
49 | * Utility class for accessing TMF trace type extensions from the platform's |
50 | * extensions registry. | |
cfd22ad0 | 51 | * |
b544077e | 52 | * @author Patrick Tasse |
d04ec5a7 | 53 | * @author Matthew Khouzam |
b544077e | 54 | */ |
d04ec5a7 | 55 | public final class TmfTraceType { |
4bf17f4a | 56 | |
a4a116c3 PT |
57 | // ------------------------------------------------------------------ |
58 | // Constants | |
59 | // ------------------------------------------------------------------ | |
60 | ||
47aafe74 | 61 | /** Extension point ID */ |
a926c25c | 62 | public static final String TMF_TRACE_TYPE_ID = "org.eclipse.linuxtools.tmf.core.tracetype"; //$NON-NLS-1$ |
4bf17f4a | 63 | |
47aafe74 | 64 | /** Extension point element 'Category' */ |
4bf17f4a | 65 | public static final String CATEGORY_ELEM = "category"; //$NON-NLS-1$ |
47aafe74 AM |
66 | |
67 | /** Extension point element 'Type' */ | |
4bf17f4a | 68 | public static final String TYPE_ELEM = "type"; //$NON-NLS-1$ |
47aafe74 | 69 | |
1ec2ca01 GB |
70 | /** Extension point element 'Experiment' */ |
71 | public static final String EXPERIMENT_ELEM = "experiment"; //$NON-NLS-1$ | |
72 | ||
47aafe74 | 73 | /** Extension point attribute 'ID' */ |
4bf17f4a | 74 | public static final String ID_ATTR = "id"; //$NON-NLS-1$ |
47aafe74 AM |
75 | |
76 | /** Extension point attribute 'name' */ | |
4bf17f4a | 77 | public static final String NAME_ATTR = "name"; //$NON-NLS-1$ |
47aafe74 AM |
78 | |
79 | /** Extension point attribute 'category' */ | |
4bf17f4a | 80 | public static final String CATEGORY_ATTR = "category"; //$NON-NLS-1$ |
47aafe74 AM |
81 | |
82 | /** Extension point attribute 'trace_type' */ | |
4bf17f4a | 83 | public static final String TRACE_TYPE_ATTR = "trace_type"; //$NON-NLS-1$ |
47aafe74 AM |
84 | |
85 | /** Extension point attribute 'event_type' */ | |
4bf17f4a | 86 | public static final String EVENT_TYPE_ATTR = "event_type"; //$NON-NLS-1$ |
47aafe74 | 87 | |
1ec2ca01 GB |
88 | /** Extension point attribute 'experiment_type' */ |
89 | public static final String EXPERIMENT_TYPE_ATTR = "experiment_type"; //$NON-NLS-1$ | |
90 | ||
d8aba2e2 BH |
91 | /** Extension point attribute 'isDirectory' */ |
92 | public static final String IS_DIR_ATTR = "isDirectory"; //$NON-NLS-1$ | |
93 | ||
1ec2ca01 GB |
94 | /** Default experiment type */ |
95 | public static final String DEFAULT_EXPERIMENT_TYPE = "org.eclipse.linuxtools.tmf.core.experiment.generic"; //$NON-NLS-1$ | |
96 | ||
d04ec5a7 MK |
97 | // The mapping of available trace type IDs to their corresponding |
98 | // configuration element | |
a4a116c3 PT |
99 | private static final Map<String, IConfigurationElement> TRACE_TYPE_ATTRIBUTES = new HashMap<>(); |
100 | private static final Map<String, IConfigurationElement> TRACE_CATEGORIES = new HashMap<>(); | |
101 | private static final Map<String, TraceTypeHelper> TRACE_TYPES = new LinkedHashMap<>(); | |
d04ec5a7 | 102 | |
a4a116c3 PT |
103 | static { |
104 | populateCategoriesAndTraceTypes(); | |
105 | populateCustomTraceTypes(); | |
106 | } | |
d04ec5a7 | 107 | |
376fdfbd GB |
108 | /** |
109 | * Enum to say whether a type applies to a trace or experiment | |
110 | * | |
111 | * @author Geneviève Bastien | |
112 | */ | |
113 | public enum TraceElementType { | |
114 | /** Trace type applies to trace */ | |
115 | TRACE, | |
116 | /** Trace type applies to experiment */ | |
117 | EXPERIMENT, | |
118 | } | |
119 | ||
a4a116c3 PT |
120 | // ------------------------------------------------------------------ |
121 | // Constructor | |
122 | // ------------------------------------------------------------------ | |
123 | ||
124 | private TmfTraceType() { | |
125 | } | |
126 | ||
127 | // ------------------------------------------------------------------ | |
128 | // Operations | |
129 | // ------------------------------------------------------------------ | |
130 | ||
d04ec5a7 MK |
131 | /** |
132 | * Retrieves the category name from the platform extension registry based on | |
133 | * the category ID | |
134 | * | |
135 | * @param categoryId | |
136 | * The category ID | |
b544077e BH |
137 | * @return the category name or empty string if not found |
138 | */ | |
4bf17f4a | 139 | public static String getCategoryName(String categoryId) { |
140 | IConfigurationElement[] elements = Platform.getExtensionRegistry() | |
141 | .getConfigurationElementsFor(TMF_TRACE_TYPE_ID); | |
142 | for (IConfigurationElement element : elements) { | |
09154cfe | 143 | if (element.getName().equals(CATEGORY_ELEM) && element.getAttribute(ID_ATTR).equals(categoryId)) { |
4bf17f4a | 144 | return element.getAttribute(NAME_ATTR); |
145 | } | |
146 | } | |
147 | return ""; //$NON-NLS-1$ | |
148 | } | |
149 | ||
b544077e | 150 | /** |
cfd22ad0 | 151 | * Retrieves all configuration elements from the platform extension registry |
376fdfbd | 152 | * for the trace type extension that apply to traces and not experiments. |
cfd22ad0 MD |
153 | * |
154 | * @return an array of trace type configuration elements | |
b544077e | 155 | */ |
4bf17f4a | 156 | public static IConfigurationElement[] getTypeElements() { |
157 | IConfigurationElement[] elements = Platform.getExtensionRegistry() | |
158 | .getConfigurationElementsFor(TMF_TRACE_TYPE_ID); | |
507b1336 | 159 | List<IConfigurationElement> typeElements = new LinkedList<>(); |
4bf17f4a | 160 | for (IConfigurationElement element : elements) { |
161 | if (element.getName().equals(TYPE_ELEM)) { | |
162 | typeElements.add(element); | |
163 | } | |
164 | } | |
beae214a | 165 | return typeElements.toArray(new IConfigurationElement[typeElements.size()]); |
4bf17f4a | 166 | } |
d04ec5a7 | 167 | |
47aafe74 AM |
168 | /** |
169 | * Get an iterable view of the existing trace type IDs. | |
170 | * | |
171 | * @return The currently registered trace type IDs | |
172 | */ | |
a4a116c3 PT |
173 | public static Iterable<String> getTraceTypeIDs() { |
174 | return TRACE_TYPES.keySet(); | |
47aafe74 AM |
175 | } |
176 | ||
252c602c BH |
177 | /** |
178 | * Get an iterable view of the existing trace type helpers. | |
179 | * | |
180 | * @return The currently registered trace type helpers | |
181 | */ | |
a4a116c3 PT |
182 | public static Iterable<TraceTypeHelper> getTraceTypeHelpers() { |
183 | return TRACE_TYPES.values(); | |
252c602c BH |
184 | } |
185 | ||
d04ec5a7 | 186 | /** |
2b0005f0 | 187 | * Returns a list of trace type labels "category : name", ... |
d04ec5a7 | 188 | * |
376fdfbd GB |
189 | * Returns only trace types, not experiment types |
190 | * | |
2b0005f0 | 191 | * @return a list of trace type labels |
d04ec5a7 | 192 | */ |
a4a116c3 | 193 | public static String[] getAvailableTraceTypes() { |
252c602c BH |
194 | return getAvailableTraceTypes(null); |
195 | } | |
196 | ||
197 | /** | |
88424bb7 MK |
198 | * Returns a list of trace type labels "category : name", ... sorted by |
199 | * given comparator. | |
252c602c | 200 | * |
376fdfbd GB |
201 | * Returns only trace types, not experiment types |
202 | * | |
252c602c BH |
203 | * @param comparator |
204 | * Comparator class (type String) or null for alphabetical order. | |
88424bb7 MK |
205 | * @return a list of trace type labels sorted according to the given |
206 | * comparator | |
252c602c | 207 | */ |
a4a116c3 | 208 | public static String[] getAvailableTraceTypes(Comparator<String> comparator) { |
d04ec5a7 MK |
209 | |
210 | // Generate the list of Category:TraceType to populate the ComboBox | |
507b1336 | 211 | List<String> traceTypes = new ArrayList<>(); |
d04ec5a7 | 212 | |
88424bb7 | 213 | for (TraceTypeHelper tt : TRACE_TYPES.values()) { |
376fdfbd | 214 | if (!tt.isExperimentType()) { |
2b0005f0 | 215 | traceTypes.add(tt.getLabel()); |
376fdfbd | 216 | } |
d04ec5a7 | 217 | } |
d04ec5a7 | 218 | |
252c602c BH |
219 | if (comparator == null) { |
220 | Collections.sort(traceTypes); | |
221 | } else { | |
222 | Collections.sort(traceTypes, comparator); | |
223 | } | |
224 | ||
d04ec5a7 MK |
225 | // Format result |
226 | return traceTypes.toArray(new String[traceTypes.size()]); | |
227 | } | |
228 | ||
229 | /** | |
d04ec5a7 MK |
230 | * Gets all the custom trace types |
231 | * | |
232 | * @return the list of custom trace types | |
d04ec5a7 | 233 | */ |
52885aeb PT |
234 | public static List<String> getCustomTraceTypes() { |
235 | ||
507b1336 | 236 | List<String> traceTypes = new ArrayList<>(); |
52885aeb PT |
237 | for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) { |
238 | String traceTypeName = def.definitionName; | |
239 | traceTypes.add(traceTypeName); | |
240 | } | |
241 | for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) { | |
242 | String traceTypeName = def.definitionName; | |
243 | traceTypes.add(traceTypeName); | |
d04ec5a7 | 244 | } |
52885aeb PT |
245 | return traceTypes; |
246 | } | |
d04ec5a7 | 247 | |
a4a116c3 | 248 | private static void populateCustomTraceTypes() { |
d04ec5a7 MK |
249 | // add the custom trace types |
250 | for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) { | |
2b0005f0 PT |
251 | CustomTxtTrace trace = new CustomTxtTrace(def); |
252 | String traceTypeId = trace.getTraceTypeId(); | |
4b3b667b | 253 | TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, def.categoryName, def.definitionName, trace, false, TraceElementType.TRACE); |
a4a116c3 | 254 | TRACE_TYPES.put(traceTypeId, tt); |
88424bb7 MK |
255 | // Deregister trace as signal handler because it is only used for |
256 | // validation | |
72807127 | 257 | TmfSignalManager.deregister(trace); |
d04ec5a7 MK |
258 | } |
259 | for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) { | |
2b0005f0 PT |
260 | CustomXmlTrace trace = new CustomXmlTrace(def); |
261 | String traceTypeId = trace.getTraceTypeId(); | |
4b3b667b | 262 | TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, def.categoryName, def.definitionName, trace, false, TraceElementType.TRACE); |
a4a116c3 | 263 | TRACE_TYPES.put(traceTypeId, tt); |
88424bb7 MK |
264 | // Deregister trace as signal handler because it is only used for |
265 | // validation | |
72807127 | 266 | TmfSignalManager.deregister(trace); |
d04ec5a7 | 267 | } |
52885aeb PT |
268 | } |
269 | ||
270 | /** | |
271 | * Add or replace a custom trace type | |
272 | * | |
4b3b667b PT |
273 | * @param traceClass |
274 | * The custom trace class, either {@link CustomTxtTrace} or | |
275 | * {@link CustomXmlTrace} | |
276 | * @param category | |
277 | * The custom parser category | |
278 | * @param definitionName | |
279 | * The custom parser definition name to add or replace | |
280 | */ | |
281 | public static void addCustomTraceType(Class<? extends ITmfTrace> traceClass, String category, String definitionName) { | |
52885aeb | 282 | String traceTypeId = null; |
c9b31f60 | 283 | ITmfTrace trace = null; |
52885aeb | 284 | |
4b3b667b | 285 | if (traceClass.equals(CustomTxtTrace.class)) { |
332527a4 | 286 | CustomTxtTraceDefinition def = CustomTxtTraceDefinition.load(category, definitionName); |
52885aeb PT |
287 | if (def != null) { |
288 | trace = new CustomTxtTrace(def); | |
2b0005f0 | 289 | traceTypeId = trace.getTraceTypeId(); |
52885aeb | 290 | } |
4b3b667b | 291 | } else if (traceClass.equals(CustomXmlTrace.class)) { |
332527a4 | 292 | CustomXmlTraceDefinition def = CustomXmlTraceDefinition.load(category, definitionName); |
52885aeb PT |
293 | if (def != null) { |
294 | trace = new CustomXmlTrace(def); | |
2b0005f0 | 295 | traceTypeId = trace.getTraceTypeId(); |
52885aeb PT |
296 | } |
297 | } | |
298 | ||
299 | if (traceTypeId != null && trace != null) { | |
a4a116c3 | 300 | TraceTypeHelper helper = TRACE_TYPES.get(traceTypeId); |
52885aeb PT |
301 | if (helper != null) { |
302 | helper.getTrace().dispose(); | |
303 | } | |
376fdfbd | 304 | TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, category, definitionName, trace, false, TraceElementType.TRACE); |
a4a116c3 | 305 | TRACE_TYPES.put(traceTypeId, tt); |
88424bb7 MK |
306 | // Deregister trace as signal handler because it is only used for |
307 | // validation | |
52885aeb PT |
308 | TmfSignalManager.deregister(trace); |
309 | } | |
310 | } | |
311 | ||
4b3b667b PT |
312 | /** |
313 | * Remove a custom trace type | |
314 | * | |
315 | * @param traceClass | |
316 | * The custom trace class, either {@link CustomTxtTrace} or | |
317 | * {@link CustomXmlTrace} | |
318 | * @param category | |
319 | * The custom parser category | |
320 | * @param definitionName | |
321 | * The custom parser definition name to add or replace | |
322 | */ | |
323 | public static void removeCustomTraceType(Class<? extends ITmfTrace> traceClass, String category, String definitionName) { | |
c9b31f60 BH |
324 | String traceTypeId = null; |
325 | if (traceClass.equals(CustomTxtTrace.class)) { | |
326 | traceTypeId = CustomTxtTrace.buildTraceTypeId(category, definitionName); | |
327 | } else if (traceClass.equals(CustomXmlTrace.class)) { | |
328 | traceTypeId = CustomXmlTrace.buildTraceTypeId(category, definitionName); | |
329 | } | |
330 | if (traceTypeId != null) { | |
331 | TraceTypeHelper helper = TRACE_TYPES.remove(traceTypeId); | |
332 | if (helper != null) { | |
333 | helper.getTrace().dispose(); | |
334 | } | |
52885aeb | 335 | } |
d04ec5a7 MK |
336 | } |
337 | ||
338 | /** | |
339 | * Gets a trace type for a given canonical id | |
340 | * | |
341 | * @param id | |
342 | * the ID of the trace | |
343 | * @return the return type | |
d04ec5a7 | 344 | */ |
a4a116c3 PT |
345 | public static TraceTypeHelper getTraceType(String id) { |
346 | return TRACE_TYPES.get(id); | |
d04ec5a7 MK |
347 | } |
348 | ||
a4a116c3 PT |
349 | private static void populateCategoriesAndTraceTypes() { |
350 | if (TRACE_TYPES.isEmpty()) { | |
d04ec5a7 MK |
351 | // Populate the Categories and Trace Types |
352 | IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType.TMF_TRACE_TYPE_ID); | |
353 | for (IConfigurationElement ce : config) { | |
354 | String elementName = ce.getName(); | |
355 | if (elementName.equals(TmfTraceType.TYPE_ELEM)) { | |
356 | String traceTypeId = ce.getAttribute(TmfTraceType.ID_ATTR); | |
a4a116c3 | 357 | TRACE_TYPE_ATTRIBUTES.put(traceTypeId, ce); |
d04ec5a7 MK |
358 | } else if (elementName.equals(TmfTraceType.CATEGORY_ELEM)) { |
359 | String categoryId = ce.getAttribute(TmfTraceType.ID_ATTR); | |
a4a116c3 | 360 | TRACE_CATEGORIES.put(categoryId, ce); |
376fdfbd GB |
361 | } else if (elementName.equals(TmfTraceType.EXPERIMENT_ELEM)) { |
362 | String experimentTypeId = ce.getAttribute(TmfTraceType.ID_ATTR); | |
a4a116c3 | 363 | TRACE_TYPE_ATTRIBUTES.put(experimentTypeId, ce); |
d04ec5a7 MK |
364 | } |
365 | } | |
366 | // create the trace types | |
88424bb7 MK |
367 | for (Entry<String, IConfigurationElement> entry : TRACE_TYPE_ATTRIBUTES.entrySet()) { |
368 | IConfigurationElement ce = entry.getValue(); | |
d04ec5a7 MK |
369 | final String category = getCategory(ce); |
370 | final String attribute = ce.getAttribute(TmfTraceType.NAME_ATTR); | |
371 | ITmfTrace trace = null; | |
376fdfbd | 372 | TraceElementType elementType = TraceElementType.TRACE; |
d04ec5a7 | 373 | try { |
376fdfbd GB |
374 | if (ce.getName().equals(TmfTraceType.TYPE_ELEM)) { |
375 | trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.TRACE_TYPE_ATTR); | |
376 | } else if (ce.getName().equals(TmfTraceType.EXPERIMENT_ELEM)) { | |
377 | trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.EXPERIMENT_TYPE_ATTR); | |
378 | elementType = TraceElementType.EXPERIMENT; | |
379 | } | |
a8ddd783 GB |
380 | if (trace == null) { |
381 | break; | |
376fdfbd | 382 | } |
a8ddd783 GB |
383 | // Deregister trace as signal handler because it is only |
384 | // used for validation | |
385 | TmfSignalManager.deregister(trace); | |
386 | ||
387 | final String dirString = ce.getAttribute(TmfTraceType.IS_DIR_ATTR); | |
388 | boolean isDir = Boolean.parseBoolean(dirString); | |
389 | ||
88424bb7 | 390 | final String typeId = entry.getKey(); |
a8ddd783 | 391 | TraceTypeHelper tt = new TraceTypeHelper(typeId, category, attribute, trace, isDir, elementType); |
a4a116c3 | 392 | TRACE_TYPES.put(typeId, tt); |
d04ec5a7 | 393 | } catch (CoreException e) { |
d77f31da | 394 | Activator.logError("Unexpected error during populating trace types", e); //$NON-NLS-1$ |
d04ec5a7 | 395 | } |
d8aba2e2 | 396 | |
d04ec5a7 MK |
397 | } |
398 | } | |
399 | } | |
400 | ||
a4a116c3 | 401 | private static String getCategory(IConfigurationElement ce) { |
d04ec5a7 MK |
402 | final String categoryId = ce.getAttribute(TmfTraceType.CATEGORY_ATTR); |
403 | if (categoryId != null) { | |
a4a116c3 | 404 | IConfigurationElement category = TRACE_CATEGORIES.get(categoryId); |
d04ec5a7 MK |
405 | if (category != null && !category.getName().equals("")) { //$NON-NLS-1$ |
406 | return category.getAttribute(TmfTraceType.NAME_ATTR); | |
407 | } | |
408 | } | |
2b0005f0 | 409 | return ""; //$NON-NLS-1$ |
d04ec5a7 MK |
410 | } |
411 | ||
412 | /** | |
413 | * Returns the list of trace categories | |
414 | * | |
415 | * @return the list of trace categories | |
d04ec5a7 | 416 | */ |
a4a116c3 | 417 | public static List<String> getTraceCategories() { |
507b1336 | 418 | List<String> categoryNames = new ArrayList<>(); |
a94e5eff JCK |
419 | for (TraceTypeHelper helper : TRACE_TYPES.values()) { |
420 | final String categoryName = helper.getCategoryName(); | |
d04ec5a7 MK |
421 | if (!categoryNames.contains(categoryName)) { |
422 | categoryNames.add(categoryName); | |
423 | } | |
424 | } | |
425 | return categoryNames; | |
426 | } | |
427 | ||
428 | /** | |
376fdfbd GB |
429 | * Get the trace type helper classes from category name. Return only the |
430 | * trace types, not the experiment types | |
d04ec5a7 | 431 | * |
cd9821de BH |
432 | * @param categoryName |
433 | * the categoryName to lookup | |
434 | * @return a list of trace type helper classes {@link TraceTypeHelper} | |
d04ec5a7 | 435 | */ |
a4a116c3 | 436 | public static List<TraceTypeHelper> getTraceTypes(String categoryName) { |
507b1336 | 437 | List<TraceTypeHelper> traceNames = new ArrayList<>(); |
88424bb7 MK |
438 | for (TraceTypeHelper traceTypeHelper : TRACE_TYPES.values()) { |
439 | if (!traceTypeHelper.isExperimentType()) { | |
440 | final String storedCategoryName = traceTypeHelper.getCategoryName(); | |
376fdfbd | 441 | if (storedCategoryName.equals(categoryName)) { |
88424bb7 | 442 | traceNames.add(traceTypeHelper); |
376fdfbd | 443 | } |
d04ec5a7 MK |
444 | } |
445 | } | |
446 | return traceNames; | |
447 | } | |
448 | ||
d04ec5a7 MK |
449 | /** |
450 | * Validate a trace type | |
451 | * | |
452 | * @param traceTypeName | |
453 | * the trace category (canonical name) | |
454 | * @param fileName | |
455 | * the file name (and path) | |
456 | * @return true if the trace is of a valid type | |
d04ec5a7 | 457 | */ |
a4a116c3 | 458 | public static boolean validate(String traceTypeName, String fileName) { |
76fccfb0 | 459 | if (traceTypeName != null && !traceTypeName.isEmpty()) { |
a4a116c3 | 460 | final TraceTypeHelper traceTypeHelper = TRACE_TYPES.get(traceTypeName); |
0621dbae | 461 | if (traceTypeHelper == null || !traceTypeHelper.validate(fileName).isOK()) { |
d04ec5a7 MK |
462 | return false; |
463 | } | |
464 | } | |
465 | return true; | |
466 | } | |
467 | ||
468 | /** | |
469 | * Validate a trace | |
470 | * | |
471 | * @param traceToValidate | |
472 | * the trace category (canonical name) | |
473 | * @return true if the trace is of a valid type | |
d04ec5a7 | 474 | */ |
a4a116c3 | 475 | public static boolean validate(TraceValidationHelper traceToValidate) { |
d04ec5a7 MK |
476 | return validate(traceToValidate.getTraceType(), traceToValidate.getTraceToScan()); |
477 | } | |
478 | ||
d04ec5a7 MK |
479 | /** |
480 | * Get a configuration element for a given name | |
481 | * | |
482 | * @param traceType | |
483 | * the name canonical | |
484 | * @return the configuration element, can be null | |
d04ec5a7 | 485 | */ |
a4a116c3 PT |
486 | public static IConfigurationElement getTraceAttributes(String traceType) { |
487 | return TRACE_TYPE_ATTRIBUTES.get(traceType); | |
d04ec5a7 MK |
488 | } |
489 | ||
490 | /** | |
2b0005f0 | 491 | * Find the id of a trace type by its label "category : name" |
d04ec5a7 | 492 | * |
2b0005f0 PT |
493 | * @param label |
494 | * the trace type label | |
495 | * @return the trace type id | |
d04ec5a7 | 496 | */ |
2b0005f0 | 497 | public static String getTraceTypeId(String label) { |
88424bb7 MK |
498 | for (Entry<String, TraceTypeHelper> entry : TRACE_TYPES.entrySet()) { |
499 | if (entry.getValue().getLabel().equals(label)) { | |
500 | return entry.getKey(); | |
d04ec5a7 MK |
501 | } |
502 | } | |
503 | return null; | |
504 | } | |
76fccfb0 | 505 | |
252c602c | 506 | /** |
d8aba2e2 | 507 | * Checks if a trace is a valid directory trace |
88424bb7 | 508 | * |
d8aba2e2 | 509 | * @param path |
252c602c | 510 | * the file name (and path) |
88424bb7 MK |
511 | * @return <code>true</code> if the trace is a valid directory trace else |
512 | * <code>false</code> | |
252c602c | 513 | */ |
a4a116c3 | 514 | public static boolean isDirectoryTrace(String path) { |
d8aba2e2 BH |
515 | final Iterable<TraceTypeHelper> traceTypeHelpers = getTraceTypeHelpers(); |
516 | for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) { | |
517 | if (traceTypeHelper.isDirectoryTraceType() && | |
d16bb0dd | 518 | (traceTypeHelper.validate(path).getSeverity() != IStatus.ERROR)) { |
d8aba2e2 BH |
519 | return true; |
520 | } | |
252c602c BH |
521 | } |
522 | return false; | |
523 | } | |
524 | ||
525 | /** | |
526 | * @param traceType | |
88424bb7 MK |
527 | * the trace type |
528 | * @return <code>true</code> it is a directory trace type else else | |
529 | * <code>false</code> | |
252c602c | 530 | */ |
a4a116c3 | 531 | public static boolean isDirectoryTraceType(String traceType) { |
d8aba2e2 BH |
532 | if (traceType != null) { |
533 | TraceTypeHelper traceTypeHelper = getTraceType(traceType); | |
534 | if (traceTypeHelper != null) { | |
535 | return traceTypeHelper.isDirectoryTraceType(); | |
536 | } | |
1dec1830 | 537 | return false; |
252c602c | 538 | } |
d8aba2e2 | 539 | throw new IllegalArgumentException("Invalid trace type string: " + traceType); //$NON-NLS-1$ |
252c602c | 540 | } |
d8aba2e2 | 541 | |
4b3b667b PT |
542 | /** |
543 | * Get the trace type id for a resource | |
544 | * | |
545 | * @param resource | |
546 | * the resource | |
547 | * @return the trace type id or null if it is not set | |
548 | * @throws CoreException | |
549 | * if the trace type id cannot be accessed | |
4b3b667b PT |
550 | */ |
551 | public static String getTraceTypeId(IResource resource) throws CoreException { | |
552 | String traceTypeId = resource.getPersistentProperties().get(TmfCommonConstants.TRACETYPE); | |
e86f7ac4 BH |
553 | return buildCompatibilityTraceTypeId(traceTypeId); |
554 | } | |
555 | ||
556 | /** | |
557 | * This methods builds a trace type ID from a given ID taking into | |
558 | * consideration any format changes that were done for the IDs of custom | |
559 | * text or XML traces. For example, such format change took place when | |
560 | * moving to Trace Compass. Trace type IDs that are part of the plug-in | |
561 | * extension for trace types won't be changed. | |
562 | * | |
563 | * This method is useful for IDs that were persisted in the workspace before | |
564 | * the format changes (e.g. in the persistent properties of a trace | |
565 | * resource). | |
566 | * | |
567 | * It ensures backwards compatibility of the workspace for custom text and | |
568 | * XML traces. | |
569 | * | |
570 | * @param traceTypeId | |
571 | * the legacy trace type ID | |
572 | * @return the trace type ID in Trace Compass format | |
573 | */ | |
574 | public static String buildCompatibilityTraceTypeId(String traceTypeId) { | |
88424bb7 MK |
575 | // Fix custom trace type id with old class name or without category name |
576 | // for backward compatibility | |
4b3b667b | 577 | if (traceTypeId != null) { |
c9b31f60 BH |
578 | String newTraceType = CustomTxtTrace.buildCompatibilityTraceTypeId(traceTypeId); |
579 | if (newTraceType.equals(traceTypeId)) { | |
580 | newTraceType = CustomXmlTrace.buildCompatibilityTraceTypeId(traceTypeId); | |
4b3b667b | 581 | } |
c9b31f60 | 582 | return newTraceType; |
4b3b667b PT |
583 | } |
584 | return traceTypeId; | |
585 | } | |
c9b31f60 | 586 | |
281def42 BH |
587 | /** |
588 | * This method figures out the trace type of a given trace. | |
589 | * | |
590 | * @param path | |
591 | * The path of trace to import (file or directory for directory traces) | |
592 | * @param traceTypeHint | |
593 | * the ID of a trace (like "o.e.l.specifictrace" ) | |
594 | * @return a list of {@link TraceTypeHelper} sorted by confidence (highest first) | |
595 | * | |
596 | * @throws TmfTraceImportException | |
597 | * if there are errors in the trace file or no trace type found | |
598 | * for a directory trace | |
599 | * @since 2.0 | |
600 | */ | |
601 | public static @NonNull List<TraceTypeHelper> selectTraceType(String path, String traceTypeHint) throws TmfTraceImportException { | |
602 | ||
603 | Comparator<Pair<Integer, TraceTypeHelper>> comparator = new Comparator<Pair<Integer, TraceTypeHelper>>() { | |
604 | @Override | |
605 | public int compare(Pair<Integer, TraceTypeHelper> o1, Pair<Integer, TraceTypeHelper> o2) { | |
606 | int res = -o1.getFirst().compareTo(o2.getFirst()); // invert so that highest confidence is first | |
607 | if (res == 0) { | |
608 | res = o1.getSecond().getName().compareTo(o2.getSecond().getName()); | |
609 | } | |
610 | return res; | |
611 | } | |
612 | }; | |
613 | ||
614 | TreeSet<Pair<Integer, TraceTypeHelper>> validCandidates = new TreeSet<>(comparator); | |
615 | final Iterable<TraceTypeHelper> traceTypeHelpers = TmfTraceType.getTraceTypeHelpers(); | |
616 | for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) { | |
617 | if (traceTypeHelper.isExperimentType()) { | |
618 | continue; | |
619 | } | |
620 | int confidence = traceTypeHelper.validateWithConfidence(path); | |
621 | if (confidence >= 0) { | |
622 | // insert in the tree map, ordered by confidence (highest confidence first) then name | |
623 | Pair<Integer, TraceTypeHelper> element = new Pair<>(confidence, traceTypeHelper); | |
624 | validCandidates.add(element); | |
625 | } | |
626 | } | |
627 | ||
628 | List<TraceTypeHelper> returned = new ArrayList<>(); | |
629 | if (validCandidates.isEmpty()) { | |
630 | File traceFile = new File(path); | |
631 | if (traceFile.isFile()) { | |
632 | return returned; | |
633 | } | |
634 | final String errorMsg = NLS.bind(Messages.TmfOpenTraceHelper_NoTraceTypeMatch, path); | |
635 | throw new TmfTraceImportException(errorMsg); | |
636 | } | |
637 | ||
638 | if (validCandidates.size() != 1) { | |
639 | List<Pair<Integer, TraceTypeHelper>> candidates = new ArrayList<>(validCandidates); | |
640 | List<Pair<Integer, TraceTypeHelper>> reducedCandidates = reduce(candidates); | |
641 | for (Pair<Integer, TraceTypeHelper> candidatePair : reducedCandidates) { | |
642 | TraceTypeHelper candidate = candidatePair.getSecond(); | |
643 | if (candidate.getTraceTypeId().equals(traceTypeHint)) { | |
644 | returned.add(candidate); | |
645 | break; | |
646 | } | |
647 | } | |
648 | if (returned.size() == 0) { | |
649 | if (reducedCandidates.size() == 0) { | |
650 | throw new TmfTraceImportException("Error reducing trace type candidates"); //$NON-NLS-1$ | |
651 | } else if (reducedCandidates.size() == 1) { | |
652 | // Don't select the trace type if it has the lowest confidence | |
653 | if (reducedCandidates.get(0).getFirst() > 0) { | |
654 | returned.add(reducedCandidates.get(0).getSecond()); | |
655 | } | |
656 | } else { | |
657 | for (Pair<Integer, TraceTypeHelper> candidatePair : reducedCandidates) { | |
68621ce0 BH |
658 | // Don't select the trace type if it has the lowest confidence |
659 | if (candidatePair.getFirst() > 0) { | |
660 | returned.add(candidatePair.getSecond()); | |
661 | } | |
281def42 BH |
662 | } |
663 | } | |
664 | } | |
665 | } else { | |
666 | // Don't select the trace type if it has the lowest confidence | |
667 | if (validCandidates.first().getFirst() > 0) { | |
668 | returned.add(validCandidates.first().getSecond()); | |
669 | } | |
670 | } | |
671 | return returned; | |
672 | } | |
673 | ||
674 | private static List<Pair<Integer, TraceTypeHelper>> reduce(List<Pair<Integer, TraceTypeHelper>> candidates) { | |
675 | List<Pair<Integer, TraceTypeHelper>> retVal = new ArrayList<>(); | |
676 | ||
677 | // get all the tracetypes that are unique in that stage | |
678 | for (Pair<Integer, TraceTypeHelper> candidatePair : candidates) { | |
679 | TraceTypeHelper candidate = candidatePair.getSecond(); | |
680 | if (isUnique(candidate, candidates)) { | |
681 | retVal.add(candidatePair); | |
682 | } | |
683 | } | |
684 | return retVal; | |
685 | } | |
686 | ||
687 | /* | |
688 | * Only return the leaves of the trace types. Ignore custom trace types. | |
689 | */ | |
690 | private static boolean isUnique(TraceTypeHelper trace, List<Pair<Integer, TraceTypeHelper>> set) { | |
691 | if (trace.getTraceClass().equals(CustomTxtTrace.class) || | |
692 | trace.getTraceClass().equals(CustomXmlTrace.class)) { | |
693 | return true; | |
694 | } | |
695 | // check if the trace type is the leaf. we make an instance of the trace | |
696 | // type and if it is only an instance of itself, it is a leaf | |
697 | final ITmfTrace tmfTrace = trace.getTrace(); | |
698 | int count = -1; | |
699 | for (Pair<Integer, TraceTypeHelper> child : set) { | |
700 | final ITmfTrace traceCandidate = child.getSecond().getTrace(); | |
701 | if (tmfTrace.getClass().isInstance(traceCandidate)) { | |
702 | count++; | |
703 | } | |
704 | } | |
705 | return count == 0; | |
706 | } | |
707 | ||
4bf17f4a | 708 | } |