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