tmf: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / project / model / TmfTraceType.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 Ericsson, École Polytechnique de Montréal
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 * Patrick Tasse - Initial API and implementation
11 * Matthew Khouzam - Added import functionalities
12 * Geneviève Bastien - Added support for experiment types
13 * Bernd Hufmann - Updated custom trace type ID handling
14 *******************************************************************************/
15
16 package org.eclipse.tracecompass.tmf.core.project.model;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.LinkedHashMap;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27
28 import org.eclipse.core.resources.IResource;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.core.runtime.IConfigurationElement;
31 import org.eclipse.core.runtime.IStatus;
32 import org.eclipse.core.runtime.Platform;
33 import org.eclipse.tracecompass.internal.tmf.core.Activator;
34 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
35 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTrace;
36 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition;
37 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTrace;
38 import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTraceDefinition;
39 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
40 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
41
42 /**
43 * Utility class for accessing TMF trace type extensions from the platform's
44 * extensions registry.
45 *
46 * @author Patrick Tasse
47 * @author Matthew Khouzam
48 */
49 public final class TmfTraceType {
50
51 // ------------------------------------------------------------------
52 // Constants
53 // ------------------------------------------------------------------
54
55 /** Extension point ID */
56 public static final String TMF_TRACE_TYPE_ID = "org.eclipse.linuxtools.tmf.core.tracetype"; //$NON-NLS-1$
57
58 /** Extension point element 'Category' */
59 public static final String CATEGORY_ELEM = "category"; //$NON-NLS-1$
60
61 /** Extension point element 'Type' */
62 public static final String TYPE_ELEM = "type"; //$NON-NLS-1$
63
64 /** Extension point element 'Experiment' */
65 public static final String EXPERIMENT_ELEM = "experiment"; //$NON-NLS-1$
66
67 /** Extension point attribute 'ID' */
68 public static final String ID_ATTR = "id"; //$NON-NLS-1$
69
70 /** Extension point attribute 'name' */
71 public static final String NAME_ATTR = "name"; //$NON-NLS-1$
72
73 /** Extension point attribute 'category' */
74 public static final String CATEGORY_ATTR = "category"; //$NON-NLS-1$
75
76 /** Extension point attribute 'trace_type' */
77 public static final String TRACE_TYPE_ATTR = "trace_type"; //$NON-NLS-1$
78
79 /** Extension point attribute 'event_type' */
80 public static final String EVENT_TYPE_ATTR = "event_type"; //$NON-NLS-1$
81
82 /** Extension point attribute 'experiment_type' */
83 public static final String EXPERIMENT_TYPE_ATTR = "experiment_type"; //$NON-NLS-1$
84
85 /** Extension point attribute 'isDirectory' */
86 public static final String IS_DIR_ATTR = "isDirectory"; //$NON-NLS-1$
87
88 /** Default experiment type */
89 public static final String DEFAULT_EXPERIMENT_TYPE = "org.eclipse.linuxtools.tmf.core.experiment.generic"; //$NON-NLS-1$
90
91 // The mapping of available trace type IDs to their corresponding
92 // configuration element
93 private static final Map<String, IConfigurationElement> TRACE_TYPE_ATTRIBUTES = new HashMap<>();
94 private static final Map<String, IConfigurationElement> TRACE_CATEGORIES = new HashMap<>();
95 private static final Map<String, TraceTypeHelper> TRACE_TYPES = new LinkedHashMap<>();
96
97 static {
98 populateCategoriesAndTraceTypes();
99 populateCustomTraceTypes();
100 }
101
102 /**
103 * Enum to say whether a type applies to a trace or experiment
104 *
105 * @author Geneviève Bastien
106 */
107 public enum TraceElementType {
108 /** Trace type applies to trace */
109 TRACE,
110 /** Trace type applies to experiment */
111 EXPERIMENT,
112 }
113
114 // ------------------------------------------------------------------
115 // Constructor
116 // ------------------------------------------------------------------
117
118 private TmfTraceType() {
119 }
120
121 // ------------------------------------------------------------------
122 // Operations
123 // ------------------------------------------------------------------
124
125 /**
126 * Retrieves the category name from the platform extension registry based on
127 * the category ID
128 *
129 * @param categoryId
130 * The category ID
131 * @return the category name or empty string if not found
132 */
133 public static String getCategoryName(String categoryId) {
134 IConfigurationElement[] elements = Platform.getExtensionRegistry()
135 .getConfigurationElementsFor(TMF_TRACE_TYPE_ID);
136 for (IConfigurationElement element : elements) {
137 if (element.getName().equals(CATEGORY_ELEM) && element.getAttribute(ID_ATTR).equals(categoryId)) {
138 return element.getAttribute(NAME_ATTR);
139 }
140 }
141 return ""; //$NON-NLS-1$
142 }
143
144 /**
145 * Retrieves all configuration elements from the platform extension registry
146 * for the trace type extension that apply to traces and not experiments.
147 *
148 * @return an array of trace type configuration elements
149 */
150 public static IConfigurationElement[] getTypeElements() {
151 IConfigurationElement[] elements = Platform.getExtensionRegistry()
152 .getConfigurationElementsFor(TMF_TRACE_TYPE_ID);
153 List<IConfigurationElement> typeElements = new LinkedList<>();
154 for (IConfigurationElement element : elements) {
155 if (element.getName().equals(TYPE_ELEM)) {
156 typeElements.add(element);
157 }
158 }
159 return typeElements.toArray(new IConfigurationElement[typeElements.size()]);
160 }
161
162 /**
163 * Get an iterable view of the existing trace type IDs.
164 *
165 * @return The currently registered trace type IDs
166 */
167 public static Iterable<String> getTraceTypeIDs() {
168 return TRACE_TYPES.keySet();
169 }
170
171 /**
172 * Get an iterable view of the existing trace type helpers.
173 *
174 * @return The currently registered trace type helpers
175 */
176 public static Iterable<TraceTypeHelper> getTraceTypeHelpers() {
177 return TRACE_TYPES.values();
178 }
179
180 /**
181 * Returns a list of trace type labels "category : name", ...
182 *
183 * Returns only trace types, not experiment types
184 *
185 * @return a list of trace type labels
186 */
187 public static String[] getAvailableTraceTypes() {
188 return getAvailableTraceTypes(null);
189 }
190
191 /**
192 * Returns a list of trace type labels "category : name", ... sorted by
193 * given comparator.
194 *
195 * Returns only trace types, not experiment types
196 *
197 * @param comparator
198 * Comparator class (type String) or null for alphabetical order.
199 * @return a list of trace type labels sorted according to the given
200 * comparator
201 */
202 public static String[] getAvailableTraceTypes(Comparator<String> comparator) {
203
204 // Generate the list of Category:TraceType to populate the ComboBox
205 List<String> traceTypes = new ArrayList<>();
206
207 for (TraceTypeHelper tt : TRACE_TYPES.values()) {
208 if (!tt.isExperimentType()) {
209 traceTypes.add(tt.getLabel());
210 }
211 }
212
213 if (comparator == null) {
214 Collections.sort(traceTypes);
215 } else {
216 Collections.sort(traceTypes, comparator);
217 }
218
219 // Format result
220 return traceTypes.toArray(new String[traceTypes.size()]);
221 }
222
223 /**
224 * Gets all the custom trace types
225 *
226 * @return the list of custom trace types
227 */
228 public static List<String> getCustomTraceTypes() {
229
230 List<String> traceTypes = new ArrayList<>();
231 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
232 String traceTypeName = def.definitionName;
233 traceTypes.add(traceTypeName);
234 }
235 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
236 String traceTypeName = def.definitionName;
237 traceTypes.add(traceTypeName);
238 }
239 return traceTypes;
240 }
241
242 private static void populateCustomTraceTypes() {
243 // add the custom trace types
244 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
245 CustomTxtTrace trace = new CustomTxtTrace(def);
246 String traceTypeId = trace.getTraceTypeId();
247 TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, def.categoryName, def.definitionName, trace, false, TraceElementType.TRACE);
248 TRACE_TYPES.put(traceTypeId, tt);
249 // Deregister trace as signal handler because it is only used for
250 // validation
251 TmfSignalManager.deregister(trace);
252 }
253 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
254 CustomXmlTrace trace = new CustomXmlTrace(def);
255 String traceTypeId = trace.getTraceTypeId();
256 TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, def.categoryName, def.definitionName, trace, false, TraceElementType.TRACE);
257 TRACE_TYPES.put(traceTypeId, tt);
258 // Deregister trace as signal handler because it is only used for
259 // validation
260 TmfSignalManager.deregister(trace);
261 }
262 }
263
264 /**
265 * Add or replace a custom trace type
266 *
267 * @param traceClass
268 * The custom trace class, either {@link CustomTxtTrace} or
269 * {@link CustomXmlTrace}
270 * @param category
271 * The custom parser category
272 * @param definitionName
273 * The custom parser definition name to add or replace
274 */
275 public static void addCustomTraceType(Class<? extends ITmfTrace> traceClass, String category, String definitionName) {
276 String traceTypeId = null;
277 ITmfTrace trace = null;
278
279 if (traceClass.equals(CustomTxtTrace.class)) {
280 CustomTxtTraceDefinition def = CustomTxtTraceDefinition.load(category, definitionName);
281 if (def != null) {
282 trace = new CustomTxtTrace(def);
283 traceTypeId = trace.getTraceTypeId();
284 }
285 } else if (traceClass.equals(CustomXmlTrace.class)) {
286 CustomXmlTraceDefinition def = CustomXmlTraceDefinition.load(category, definitionName);
287 if (def != null) {
288 trace = new CustomXmlTrace(def);
289 traceTypeId = trace.getTraceTypeId();
290 }
291 }
292
293 if (traceTypeId != null && trace != null) {
294 TraceTypeHelper helper = TRACE_TYPES.get(traceTypeId);
295 if (helper != null) {
296 helper.getTrace().dispose();
297 }
298 TraceTypeHelper tt = new TraceTypeHelper(traceTypeId, category, definitionName, trace, false, TraceElementType.TRACE);
299 TRACE_TYPES.put(traceTypeId, tt);
300 // Deregister trace as signal handler because it is only used for
301 // validation
302 TmfSignalManager.deregister(trace);
303 }
304 }
305
306 /**
307 * Remove a custom trace type
308 *
309 * @param traceClass
310 * The custom trace class, either {@link CustomTxtTrace} or
311 * {@link CustomXmlTrace}
312 * @param category
313 * The custom parser category
314 * @param definitionName
315 * The custom parser definition name to add or replace
316 */
317 public static void removeCustomTraceType(Class<? extends ITmfTrace> traceClass, String category, String definitionName) {
318 String traceTypeId = null;
319 if (traceClass.equals(CustomTxtTrace.class)) {
320 traceTypeId = CustomTxtTrace.buildTraceTypeId(category, definitionName);
321 } else if (traceClass.equals(CustomXmlTrace.class)) {
322 traceTypeId = CustomXmlTrace.buildTraceTypeId(category, definitionName);
323 }
324 if (traceTypeId != null) {
325 TraceTypeHelper helper = TRACE_TYPES.remove(traceTypeId);
326 if (helper != null) {
327 helper.getTrace().dispose();
328 }
329 }
330 }
331
332 /**
333 * Gets a trace type for a given canonical id
334 *
335 * @param id
336 * the ID of the trace
337 * @return the return type
338 */
339 public static TraceTypeHelper getTraceType(String id) {
340 return TRACE_TYPES.get(id);
341 }
342
343 private static void populateCategoriesAndTraceTypes() {
344 if (TRACE_TYPES.isEmpty()) {
345 // Populate the Categories and Trace Types
346 IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType.TMF_TRACE_TYPE_ID);
347 for (IConfigurationElement ce : config) {
348 String elementName = ce.getName();
349 if (elementName.equals(TmfTraceType.TYPE_ELEM)) {
350 String traceTypeId = ce.getAttribute(TmfTraceType.ID_ATTR);
351 TRACE_TYPE_ATTRIBUTES.put(traceTypeId, ce);
352 } else if (elementName.equals(TmfTraceType.CATEGORY_ELEM)) {
353 String categoryId = ce.getAttribute(TmfTraceType.ID_ATTR);
354 TRACE_CATEGORIES.put(categoryId, ce);
355 } else if (elementName.equals(TmfTraceType.EXPERIMENT_ELEM)) {
356 String experimentTypeId = ce.getAttribute(TmfTraceType.ID_ATTR);
357 TRACE_TYPE_ATTRIBUTES.put(experimentTypeId, ce);
358 }
359 }
360 // create the trace types
361 for (Entry<String, IConfigurationElement> entry : TRACE_TYPE_ATTRIBUTES.entrySet()) {
362 IConfigurationElement ce = entry.getValue();
363 final String category = getCategory(ce);
364 final String attribute = ce.getAttribute(TmfTraceType.NAME_ATTR);
365 ITmfTrace trace = null;
366 TraceElementType elementType = TraceElementType.TRACE;
367 try {
368 if (ce.getName().equals(TmfTraceType.TYPE_ELEM)) {
369 trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.TRACE_TYPE_ATTR);
370 } else if (ce.getName().equals(TmfTraceType.EXPERIMENT_ELEM)) {
371 trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.EXPERIMENT_TYPE_ATTR);
372 elementType = TraceElementType.EXPERIMENT;
373 }
374 if (trace == null) {
375 break;
376 }
377 // Deregister trace as signal handler because it is only
378 // used for validation
379 TmfSignalManager.deregister(trace);
380
381 final String dirString = ce.getAttribute(TmfTraceType.IS_DIR_ATTR);
382 boolean isDir = Boolean.parseBoolean(dirString);
383
384 final String typeId = entry.getKey();
385 TraceTypeHelper tt = new TraceTypeHelper(typeId, category, attribute, trace, isDir, elementType);
386 TRACE_TYPES.put(typeId, tt);
387 } catch (CoreException e) {
388 Activator.logError("Unexpected error during populating trace types", e); //$NON-NLS-1$
389 }
390
391 }
392 }
393 }
394
395 private static String getCategory(IConfigurationElement ce) {
396 final String categoryId = ce.getAttribute(TmfTraceType.CATEGORY_ATTR);
397 if (categoryId != null) {
398 IConfigurationElement category = TRACE_CATEGORIES.get(categoryId);
399 if (category != null && !category.getName().equals("")) { //$NON-NLS-1$
400 return category.getAttribute(TmfTraceType.NAME_ATTR);
401 }
402 }
403 return ""; //$NON-NLS-1$
404 }
405
406 /**
407 * Returns the list of trace categories
408 *
409 * @return the list of trace categories
410 */
411 public static List<String> getTraceCategories() {
412 List<String> categoryNames = new ArrayList<>();
413 for (String key : TRACE_TYPES.keySet()) {
414 final String categoryName = TRACE_TYPES.get(key).getCategoryName();
415 if (!categoryNames.contains(categoryName)) {
416 categoryNames.add(categoryName);
417 }
418 }
419 return categoryNames;
420 }
421
422 /**
423 * Get the trace type helper classes from category name. Return only the
424 * trace types, not the experiment types
425 *
426 * @param categoryName
427 * the categoryName to lookup
428 * @return a list of trace type helper classes {@link TraceTypeHelper}
429 */
430 public static List<TraceTypeHelper> getTraceTypes(String categoryName) {
431 List<TraceTypeHelper> traceNames = new ArrayList<>();
432 for (TraceTypeHelper traceTypeHelper : TRACE_TYPES.values()) {
433 if (!traceTypeHelper.isExperimentType()) {
434 final String storedCategoryName = traceTypeHelper.getCategoryName();
435 if (storedCategoryName.equals(categoryName)) {
436 traceNames.add(traceTypeHelper);
437 }
438 }
439 }
440 return traceNames;
441 }
442
443 /**
444 * Validate a trace type
445 *
446 * @param traceTypeName
447 * the trace category (canonical name)
448 * @param fileName
449 * the file name (and path)
450 * @return true if the trace is of a valid type
451 */
452 public static boolean validate(String traceTypeName, String fileName) {
453 if (traceTypeName != null && !traceTypeName.isEmpty()) {
454 final TraceTypeHelper traceTypeHelper = TRACE_TYPES.get(traceTypeName);
455 if (traceTypeHelper == null || !traceTypeHelper.validate(fileName).isOK()) {
456 return false;
457 }
458 }
459 return true;
460 }
461
462 /**
463 * Validate a trace
464 *
465 * @param traceToValidate
466 * the trace category (canonical name)
467 * @return true if the trace is of a valid type
468 */
469 public static boolean validate(TraceValidationHelper traceToValidate) {
470 return validate(traceToValidate.getTraceType(), traceToValidate.getTraceToScan());
471 }
472
473 /**
474 * Get a configuration element for a given name
475 *
476 * @param traceType
477 * the name canonical
478 * @return the configuration element, can be null
479 */
480 public static IConfigurationElement getTraceAttributes(String traceType) {
481 return TRACE_TYPE_ATTRIBUTES.get(traceType);
482 }
483
484 /**
485 * Find the id of a trace type by its label "category : name"
486 *
487 * @param label
488 * the trace type label
489 * @return the trace type id
490 */
491 public static String getTraceTypeId(String label) {
492 for (Entry<String, TraceTypeHelper> entry : TRACE_TYPES.entrySet()) {
493 if (entry.getValue().getLabel().equals(label)) {
494 return entry.getKey();
495 }
496 }
497 return null;
498 }
499
500 /**
501 * Checks if a trace is a valid directory trace
502 *
503 * @param path
504 * the file name (and path)
505 * @return <code>true</code> if the trace is a valid directory trace else
506 * <code>false</code>
507 */
508 public static boolean isDirectoryTrace(String path) {
509 final Iterable<TraceTypeHelper> traceTypeHelpers = getTraceTypeHelpers();
510 for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) {
511 if (traceTypeHelper.isDirectoryTraceType() &&
512 (traceTypeHelper.validate(path).getSeverity() != IStatus.ERROR)) {
513 return true;
514 }
515 }
516 return false;
517 }
518
519 /**
520 * @param traceType
521 * the trace type
522 * @return <code>true</code> it is a directory trace type else else
523 * <code>false</code>
524 */
525 public static boolean isDirectoryTraceType(String traceType) {
526 if (traceType != null) {
527 TraceTypeHelper traceTypeHelper = getTraceType(traceType);
528 if (traceTypeHelper != null) {
529 return traceTypeHelper.isDirectoryTraceType();
530 }
531 return false;
532 }
533 throw new IllegalArgumentException("Invalid trace type string: " + traceType); //$NON-NLS-1$
534 }
535
536 /**
537 * Get the trace type id for a resource
538 *
539 * @param resource
540 * the resource
541 * @return the trace type id or null if it is not set
542 * @throws CoreException
543 * if the trace type id cannot be accessed
544 */
545 public static String getTraceTypeId(IResource resource) throws CoreException {
546 String traceTypeId = resource.getPersistentProperties().get(TmfCommonConstants.TRACETYPE);
547 return buildCompatibilityTraceTypeId(traceTypeId);
548 }
549
550 /**
551 * This methods builds a trace type ID from a given ID taking into
552 * consideration any format changes that were done for the IDs of custom
553 * text or XML traces. For example, such format change took place when
554 * moving to Trace Compass. Trace type IDs that are part of the plug-in
555 * extension for trace types won't be changed.
556 *
557 * This method is useful for IDs that were persisted in the workspace before
558 * the format changes (e.g. in the persistent properties of a trace
559 * resource).
560 *
561 * It ensures backwards compatibility of the workspace for custom text and
562 * XML traces.
563 *
564 * @param traceTypeId
565 * the legacy trace type ID
566 * @return the trace type ID in Trace Compass format
567 */
568 public static String buildCompatibilityTraceTypeId(String traceTypeId) {
569 // Fix custom trace type id with old class name or without category name
570 // for backward compatibility
571 if (traceTypeId != null) {
572 String newTraceType = CustomTxtTrace.buildCompatibilityTraceTypeId(traceTypeId);
573 if (newTraceType.equals(traceTypeId)) {
574 newTraceType = CustomXmlTrace.buildCompatibilityTraceTypeId(traceTypeId);
575 }
576 return newTraceType;
577 }
578 return traceTypeId;
579 }
580
581 }
This page took 0.053285 seconds and 6 git commands to generate.