tmf: Support folders in tracing projects
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / project / model / TmfTraceTypeUIUtils.java
index 46bff53ce2487355012750f15f6afcae74f47bbf..fa0bd8291666ba3cfc6d5f77d5b62c8bafe40818 100644 (file)
@@ -8,31 +8,34 @@
  *
  * Contributors:
  *   Alexandre Montplaisir - Initial API and implementation
+ *   Patrick Tasse - Add support for folder elements
  *******************************************************************************/
 
 package org.eclipse.linuxtools.tmf.ui.project.model;
 
-import java.io.File;
 import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeSet;
 
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
-import org.eclipse.linuxtools.internal.tmf.ui.Activator;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceImportException;
 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
+import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType.TraceElementType;
 import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.core.util.Pair;
+import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
@@ -40,7 +43,6 @@ import org.eclipse.swt.layout.RowLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.dialogs.FileSystemElement;
 
 /**
  * Utils class for the UI-specific parts of @link {@link TmfTraceType}.
@@ -50,49 +52,46 @@ import org.eclipse.ui.dialogs.FileSystemElement;
  */
 public final class TmfTraceTypeUIUtils {
 
-    private static final String DEFAULT_TRACE_ICON_PATH = "icons" + File.separator + "elcl16" + File.separator + "trace.gif"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    /** Extension point ID */
+    public static final String TMF_TRACE_TYPE_UI_ID = "org.eclipse.linuxtools.tmf.ui.tracetypeui"; //$NON-NLS-1$
 
-    private static final char SEPARATOR = ':';
+    /** Extension point element 'type' (should match the type in TmfTraceType) */
+    public static final String TYPE_ELEM = "type"; //$NON-NLS-1$
 
-    private TmfTraceTypeUIUtils() {}
+    /**
+     * Extension point element 'experiment' (should match the type in
+     * TmfTraceType)
+     */
+    public static final String EXPERIMENT_ELEM = "experiment"; //$NON-NLS-1$
 
-    private static List<File> isolateTraces(List<FileSystemElement> selectedResources) {
-        List<File> traces = new ArrayList<>();
+    /** Extension point element 'Default editor' */
+    public static final String DEFAULT_EDITOR_ELEM = "defaultEditor"; //$NON-NLS-1$
 
-        // Get the selection
-        Iterator<FileSystemElement> resources = selectedResources.iterator();
+    /** Extension point element 'Events table type' */
+    public static final String EVENTS_TABLE_TYPE_ELEM = "eventsTableType"; //$NON-NLS-1$
 
-        // Get the sorted list of unique entries
-        Map<String, File> fileSystemObjects = new HashMap<>();
-        while (resources.hasNext()) {
-            File resource = (File) resources.next().getFileSystemObject();
-            String key = resource.getAbsolutePath();
-            fileSystemObjects.put(key, resource);
-        }
-        List<String> files = new ArrayList<>(fileSystemObjects.keySet());
-        Collections.sort(files);
-
-        // After sorting, traces correspond to the unique prefixes
-        String prefix = null;
-        for (int i = 0; i < files.size(); i++) {
-            File file = fileSystemObjects.get(files.get(i));
-            String name = file.getAbsolutePath();
-            if (prefix == null || !name.startsWith(prefix)) {
-                prefix = name; // new prefix
-                traces.add(file);
-            }
-        }
+    /** Extension point attribute 'tracetype' */
+    public static final String TRACETYPE_ATTR = "tracetype"; //$NON-NLS-1$
+
+    /** Extension point attribute 'icon' */
+    public static final String ICON_ATTR = "icon"; //$NON-NLS-1$
 
-        return traces;
+    /** Extension point attribute 'class' (attribute of eventsTableType) */
+    public static final String CLASS_ATTR = "class"; //$NON-NLS-1$
+
+    private static final char SEPARATOR = ':';
+
+    private TmfTraceTypeUIUtils() {
     }
 
-    private static List<TraceTypeHelper> reduce(List<TraceTypeHelper> candidates) {
-        List<TraceTypeHelper> retVal = new ArrayList<>();
+    private static List<Pair<Integer, TraceTypeHelper>> reduce(List<Pair<Integer, TraceTypeHelper>> candidates) {
+        List<Pair<Integer, TraceTypeHelper>> retVal = new ArrayList<>();
 
         // get all the tracetypes that are unique in that stage
-        for (TraceTypeHelper trace : candidates) {
-            if (isUnique(trace, candidates)) {
-                retVal.add(trace);
+        for (Pair<Integer, TraceTypeHelper> candidatePair : candidates) {
+            TraceTypeHelper candidate = candidatePair.getSecond();
+            if (isUnique(candidate, candidates)) {
+                retVal.add(candidatePair);
             }
         }
         return retVal;
@@ -101,7 +100,7 @@ public final class TmfTraceTypeUIUtils {
     /*
      * Only return the leaves of the trace types. Ignore custom trace types.
      */
-    private static boolean isUnique(TraceTypeHelper trace, List<TraceTypeHelper> set) {
+    private static boolean isUnique(TraceTypeHelper trace, List<Pair<Integer, TraceTypeHelper>> set) {
         if (isCustomTraceId(trace.getCanonicalName())) {
             return true;
         }
@@ -109,8 +108,8 @@ public final class TmfTraceTypeUIUtils {
         // type and if it is only an instance of itself, it is a leaf
         final ITmfTrace tmfTrace = trace.getTrace();
         int count = -1;
-        for (TraceTypeHelper child : set) {
-            final ITmfTrace traceCandidate = child.getTrace();
+        for (Pair<Integer, TraceTypeHelper> child : set) {
+            final ITmfTrace traceCandidate = child.getSecond().getTrace();
             if (tmfTrace.getClass().isInstance(traceCandidate)) {
                 count++;
             }
@@ -134,12 +133,13 @@ public final class TmfTraceTypeUIUtils {
         return false;
     }
 
-    private static TraceTypeHelper getTraceTypeToSet(TmfTraceType type, List<TraceTypeHelper> candidates, Shell shell) {
+    private static TraceTypeHelper getTraceTypeToSet(TmfTraceType type, List<Pair<Integer, TraceTypeHelper>> candidates, Shell shell) {
         final Map<String, String> names = new HashMap<>();
         Shell shellToShow = new Shell(shell);
         shellToShow.setText(Messages.TmfTraceType_SelectTraceType);
         final String candidatesToSet[] = new String[1];
-        for (TraceTypeHelper candidate : candidates) {
+        for (Pair<Integer, TraceTypeHelper> candidatePair : candidates) {
+            TraceTypeHelper candidate = candidatePair.getSecond();
             Button b = new Button(shellToShow, SWT.RADIO);
             final String displayName = candidate.getCategoryName() + ':' + candidate.getName();
             b.setText(displayName);
@@ -173,22 +173,6 @@ public final class TmfTraceTypeUIUtils {
         return type.getTraceTypeHelper(candidatesToSet[0]);
     }
 
-    /**
-     * validate list of traces with a tracetype
-     *
-     * @param type
-     *            The TmfTraceType instance
-     * @param traceTypeName
-     *            the trace category (canonical name)
-     * @param selectedResources
-     *            List of traces to validate
-     * @return true if all the traces are valid
-     */
-    public static boolean validateTrace(TmfTraceType type, String traceTypeName, List<FileSystemElement> selectedResources) {
-        List<File> traces = isolateTraces(selectedResources);
-        return type.validateTraceFiles(traceTypeName, traces);
-    }
-
     /**
      * This member figures out the trace type of a given file. It will prompt
      * the user if it needs more information to properly pick the trace type.
@@ -208,82 +192,159 @@ public final class TmfTraceTypeUIUtils {
      */
     public static TraceTypeHelper selectTraceType(String path, Shell shell, String traceTypeHint) throws TmfTraceImportException {
         TmfTraceType type = TmfTraceType.getInstance();
-        List<TraceTypeHelper> validCandidates = new ArrayList<>();
-        final Iterable<String> traceTypes = type.getTraceTypeIDs();
-        for (String traceType : traceTypes) {
-            if (type.validate(traceType, path)) {
-                validCandidates.add(type.getTraceTypeHelper(traceType));
+
+        Comparator<Pair<Integer, TraceTypeHelper>> comparator = new Comparator<Pair<Integer, TraceTypeHelper>>() {
+            @Override
+            public int compare(Pair<Integer, TraceTypeHelper> o1, Pair<Integer, TraceTypeHelper> o2) {
+                int res = -o1.getFirst().compareTo(o2.getFirst()); // invert so that highest confidence is first
+                if (res == 0) {
+                    res = o1.getSecond().getName().compareTo(o2.getSecond().getName());
+                }
+                return res;
+            }
+        };
+        TreeSet<Pair<Integer, TraceTypeHelper>> validCandidates = new TreeSet<>(comparator);
+        final Iterable<TraceTypeHelper> traceTypeHelpers = type.getTraceTypeHelpers();
+        for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) {
+            if (traceTypeHelper.isExperimentType()) {
+                continue;
+            }
+            int confidence = traceTypeHelper.validateWithConfidence(path);
+            if (confidence >= 0) {
+                // insert in the tree map, ordered by confidence (highest confidence first) then name
+                Pair<Integer, TraceTypeHelper> element = new Pair<>(confidence, traceTypeHelper);
+                validCandidates.add(element);
             }
         }
 
         TraceTypeHelper traceTypeToSet = null;
         if (validCandidates.isEmpty()) {
-            final String errorMsg = Messages.TmfOpenTraceHelper_NoTraceTypeMatch + path;
+            final String errorMsg = NLS.bind(Messages.TmfOpenTraceHelper_NoTraceTypeMatch, path);
             throw new TmfTraceImportException(errorMsg);
         } else if (validCandidates.size() != 1) {
-            List<TraceTypeHelper> reducedCandidates = reduce(validCandidates);
-            for (TraceTypeHelper tth : reducedCandidates) {
-                if (tth.getCanonicalName().equals(traceTypeHint)) {
-                    traceTypeToSet = tth;
+            List<Pair<Integer, TraceTypeHelper>> candidates = new ArrayList<>(validCandidates);
+            List<Pair<Integer, TraceTypeHelper>> reducedCandidates = reduce(candidates);
+            for (Pair<Integer, TraceTypeHelper> candidatePair : reducedCandidates) {
+                TraceTypeHelper candidate = candidatePair.getSecond();
+                if (candidate.getCanonicalName().equals(traceTypeHint)) {
+                    traceTypeToSet = candidate;
+                    break;
                 }
             }
             if (traceTypeToSet == null) {
                 if (reducedCandidates.size() == 0) {
                     throw new TmfTraceImportException(Messages.TmfOpenTraceHelper_ReduceError);
                 } else if (reducedCandidates.size() == 1) {
-                    traceTypeToSet = reducedCandidates.get(0);
-                } else {
-                    if (shell == null) {
-                        return null;
+                    traceTypeToSet = reducedCandidates.get(0).getSecond();
+                } else if (shell == null) {
+                    Pair<Integer, TraceTypeHelper> candidate = reducedCandidates.get(0);
+                    // if the best match has lowest confidence, don't select it
+                    if (candidate.getFirst() > 0) {
+                        traceTypeToSet = candidate.getSecond();
                     }
+                } else {
                     traceTypeToSet = getTraceTypeToSet(type, reducedCandidates, shell);
                 }
             }
         } else {
-            traceTypeToSet = validCandidates.get(0);
+            traceTypeToSet = validCandidates.first().getSecond();
         }
         return traceTypeToSet;
     }
 
-
     /**
      * Set the trace type of a {@Link TraceTypeHelper}. Should only be
      * used internally by this project.
      *
-     * @param path
-     *            the {@link IPath} path of the resource to set
+     * @param resource
+     *            the resource to set
      * @param traceType
      *            the {@link TraceTypeHelper} to set the trace type to.
      * @return Status.OK_Status if successful, error is otherwise.
      * @throws CoreException
      *             An exception caused by accessing eclipse project items.
      */
-    public static IStatus setTraceType(IPath path, TraceTypeHelper traceType) throws CoreException {
-        IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
-        String traceBundle = null, traceTypeId = traceType.getCanonicalName(), traceIcon = null;
-        if (isCustomTraceId(traceTypeId)) {
-            traceBundle = Activator.getDefault().getBundle().getSymbolicName();
-            traceIcon = DEFAULT_TRACE_ICON_PATH;
-        } else {
-            IConfigurationElement ce = TmfTraceType.getInstance().getTraceAttributes(traceTypeId);
-            traceBundle = ce.getContributor().getName();
-            traceIcon = ce.getAttribute(TmfTraceType.ICON_ATTR);
-        }
+    public static IStatus setTraceType(IResource resource, TraceTypeHelper traceType) throws CoreException {
+        String traceTypeId = traceType.getCanonicalName();
 
-        resource.setPersistentProperty(TmfCommonConstants.TRACEBUNDLE, traceBundle);
         resource.setPersistentProperty(TmfCommonConstants.TRACETYPE, traceTypeId);
-        resource.setPersistentProperty(TmfCommonConstants.TRACEICON, traceIcon);
 
         TmfProjectElement tmfProject = TmfProjectRegistry.getProject(resource.getProject(), true);
-        final TmfTraceFolder tracesFolder = tmfProject.getTracesFolder();
-        List<TmfTraceElement> traces = tracesFolder.getTraces();
-        for (TmfTraceElement traceElement : traces) {
-            if (traceElement.getName().equals(resource.getName())) {
-                traceElement.refreshTraceType();
-                break;
+        if (tmfProject.getTracesFolder().getPath().isPrefixOf(resource.getFullPath())) {
+            String elementPath = resource.getFullPath().makeRelativeTo(tmfProject.getTracesFolder().getPath()).toString();
+            refreshTraceElement(tmfProject.getTracesFolder().getTraces(), elementPath);
+        } else if (resource.getParent().equals(tmfProject.getExperimentsFolder().getResource())) {
+            /* The trace type to set is for an experiment */
+            for (TmfExperimentElement experimentElement : tmfProject.getExperimentsFolder().getExperiments()) {
+                if (resource.equals(experimentElement.getResource())) {
+                    experimentElement.refreshTraceType();
+                    break;
+                }
+            }
+        } else {
+            for (TmfExperimentElement experimentElement : tmfProject.getExperimentsFolder().getExperiments()) {
+                if (experimentElement.getPath().isPrefixOf(resource.getFullPath())) {
+                    String elementPath = resource.getFullPath().makeRelativeTo(experimentElement.getPath()).toString();
+                    refreshTraceElement(experimentElement.getTraces(), elementPath);
+                    break;
+                }
             }
         }
         tmfProject.refresh();
         return Status.OK_STATUS;
     }
+
+    private static void refreshTraceElement(List<TmfTraceElement> traceElements, String elementPath) {
+        for (TmfTraceElement traceElement : traceElements) {
+            if (traceElement.getElementPath().equals(elementPath)) {
+                traceElement.refreshTraceType();
+                break;
+            }
+        }
+    }
+
+    /**
+     * Retrieves all configuration elements from the platform extension registry
+     * for the trace type UI extension.
+     *
+     * @param elType
+     *            The type of trace type requested, either TRACE or EXPERIMENT
+     * @return An array of trace type configuration elements
+     */
+    public static IConfigurationElement[] getTypeUIElements(TraceElementType elType) {
+        String elementName = TYPE_ELEM;
+        if (elType == TraceElementType.EXPERIMENT) {
+            elementName = EXPERIMENT_ELEM;
+        }
+        IConfigurationElement[] elements =
+                Platform.getExtensionRegistry().getConfigurationElementsFor(TMF_TRACE_TYPE_UI_ID);
+        List<IConfigurationElement> typeElements = new LinkedList<>();
+        for (IConfigurationElement element : elements) {
+            if (element.getName().equals(elementName)) {
+                typeElements.add(element);
+            }
+        }
+        return typeElements.toArray(new IConfigurationElement[typeElements.size()]);
+    }
+
+    /**
+     * Get the UI elements for the given trace type
+     *
+     * @param traceType
+     *            The tracetype ID
+     * @param elType
+     *            The type of trace type requested, either TRACE or EXPERIMENT
+     * @return The top-level configuration element (access its children with
+     *         .getChildren()). Or null if there is no such element.
+     */
+    @Nullable
+    public static IConfigurationElement getTraceUIAttributes(String traceType, TraceElementType elType) {
+        IConfigurationElement[] elements = getTypeUIElements(elType);
+        for (IConfigurationElement ce : elements) {
+            if (traceType.equals(ce.getAttribute(TRACETYPE_ATTR))) {
+                return ce;
+            }
+        }
+        return null;
+    }
 }
This page took 0.030054 seconds and 5 git commands to generate.